phpseclib/Net/SSH2.php
- 1
<?php
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75 define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
- 76 define('NET_SSH2_MASK_CONNECTED', 0x00000002);
- 77 define('NET_SSH2_MASK_LOGIN_REQ', 0x00000004);
- 78 define('NET_SSH2_MASK_LOGIN', 0x00000008);
- 79 define('NET_SSH2_MASK_SHELL', 0x00000010);
- 80 define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020);
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99 define('NET_SSH2_CHANNEL_EXEC', 1);
- 100 define('NET_SSH2_CHANNEL_SHELL', 2);
- 101 define('NET_SSH2_CHANNEL_SUBSYSTEM', 3);
- 102 define('NET_SSH2_CHANNEL_AGENT_FORWARD', 4);
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112 define('NET_SSH2_LOG_SIMPLE', 1);
- 113
- 114
- 115
- 116 define('NET_SSH2_LOG_COMPLEX', 2);
- 117
- 118
- 119
- 120 define('NET_SSH2_LOG_REALTIME', 3);
- 121
- 122
- 123
- 124 define('NET_SSH2_LOG_REALTIME_FILE', 4);
- 125
- 126
- 127
- 128 define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024);
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138 define('NET_SSH2_READ_SIMPLE', 1);
- 139
- 140
- 141
- 142 define('NET_SSH2_READ_REGEX', 2);
- 143
- 144
- 145
- 146 define('NET_SSH2_READ_NEXT', 3);
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156 class Net_SSH2
- 157 {
- 158
- 159
- 160
- 161
- 162
- 163
- 164 var $identifier;
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172 var $fsock;
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183 var $bitmap = 0;
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193 var $errors = array();
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202 var $server_identifier = false;
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211 var $kex_algorithms = false;
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220 var $kex_dh_group_size_min = 1536;
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229 var $kex_dh_group_size_preferred = 2048;
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238 var $kex_dh_group_size_max = 4096;
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247 var $server_host_key_algorithms = false;
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256 var $encryption_algorithms_client_to_server = false;
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265 var $encryption_algorithms_server_to_client = false;
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274 var $mac_algorithms_client_to_server = false;
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283 var $mac_algorithms_server_to_client = false;
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292 var $compression_algorithms_client_to_server = false;
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301 var $compression_algorithms_server_to_client = false;
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310 var $languages_server_to_client = false;
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319 var $languages_client_to_server = false;
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336 var $encrypt_block_size = 8;
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346 var $decrypt_block_size = 8;
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355 var $decrypt = false;
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364 var $encrypt = false;
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373 var $hmac_create = false;
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382 var $hmac_check = false;
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395 var $hmac_size = false;
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404 var $server_public_host_key;
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419 var $session_id = false;
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430 var $exchange_hash = false;
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439 var $message_numbers = array();
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448 var $disconnect_reasons = array();
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457 var $channel_open_failure_reasons = array();
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467 var $terminal_modes = array();
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477 var $channel_extended_data_type_codes = array();
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488 var $send_seq_no = 0;
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499 var $get_seq_no = 0;
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511 var $server_channels = array();
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524 var $channel_buffers = array();
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535 var $channel_status = array();
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546 var $packet_size_client_to_server = array();
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555 var $message_number_log = array();
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564 var $message_log = array();
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576 var $window_size = 0x7FFFFFFF;
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587 var $window_size_server_to_client = array();
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598 var $window_size_client_to_server = array();
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609 var $signature = '';
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620 var $signature_format = '';
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629 var $interactiveBuffer = '';
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641 var $log_size;
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649 var $timeout;
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657 var $curTimeout;
- 658
- 659
- 660
- 661
- 662
- 663
- 664
- 665
- 666 var $realtime_log_file;
- 667
- 668
- 669
- 670
- 671
- 672
- 673
- 674
- 675 var $realtime_log_size;
- 676
- 677
- 678
- 679
- 680
- 681
- 682
- 683
- 684 var $signature_validated = false;
- 685
- 686
- 687
- 688
- 689
- 690
- 691
- 692 var $realtime_log_wrap;
- 693
- 694
- 695
- 696
- 697
- 698
- 699
- 700 var $quiet_mode = false;
- 701
- 702
- 703
- 704
- 705
- 706
- 707
- 708 var $last_packet;
- 709
- 710
- 711
- 712
- 713
- 714
- 715
- 716 var $exit_status;
- 717
- 718
- 719
- 720
- 721
- 722
- 723
- 724
- 725 var $request_pty = false;
- 726
- 727
- 728
- 729
- 730
- 731
- 732
- 733 var $in_request_pty_exec = false;
- 734
- 735
- 736
- 737
- 738
- 739
- 740
- 741 var $in_subsystem;
- 742
- 743
- 744
- 745
- 746
- 747
- 748
- 749 var $stdErrorLog;
- 750
- 751
- 752
- 753
- 754
- 755
- 756
- 757
- 758 var $last_interactive_response = '';
- 759
- 760
- 761
- 762
- 763
- 764
- 765
- 766
- 767 var $keyboard_requests_responses = array();
- 768
- 769
- 770
- 771
- 772
- 773
- 774
- 775
- 776
- 777
- 778
- 779
- 780 var $banner_message = '';
- 781
- 782
- 783
- 784
- 785
- 786
- 787
- 788
- 789 var $is_timeout = false;
- 790
- 791
- 792
- 793
- 794
- 795
- 796
- 797
- 798 var $log_boundary = ':';
- 799
- 800
- 801
- 802
- 803
- 804
- 805
- 806
- 807 var $log_long_width = 65;
- 808
- 809
- 810
- 811
- 812
- 813
- 814
- 815
- 816 var $log_short_width = 16;
- 817
- 818
- 819
- 820
- 821
- 822
- 823
- 824
- 825
- 826 var $host;
- 827
- 828
- 829
- 830
- 831
- 832
- 833
- 834
- 835
- 836 var $port;
- 837
- 838
- 839
- 840
- 841
- 842
- 843
- 844
- 845
- 846
- 847 var $windowColumns = 80;
- 848
- 849
- 850
- 851
- 852
- 853
- 854
- 855
- 856
- 857
- 858 var $windowRows = 24;
- 859
- 860
- 861
- 862
- 863
- 864
- 865
- 866
- 867
- 868 var $crypto_engine = false;
- 869
- 870
- 871
- 872
- 873
- 874
- 875
- 876 var $agent;
- 877
- 878
- 879
- 880
- 881
- 882
- 883
- 884 var $send_id_string_first = true;
- 885
- 886
- 887
- 888
- 889
- 890
- 891
- 892 var $send_kex_first = true;
- 893
- 894
- 895
- 896
- 897
- 898
- 899
- 900 var $bad_key_size_fix = false;
- 901
- 902
- 903
- 904
- 905
- 906
- 907
- 908 var $decrypt_algorithm = '';
- 909
- 910
- 911
- 912
- 913
- 914
- 915
- 916 var $retry_connect = false;
- 917
- 918
- 919
- 920
- 921
- 922
- 923
- 924 var $binary_packet_buffer = false;
- 925
- 926
- 927
- 928
- 929
- 930
- 931
- 932
- 933
- 934
- 935
- 936
- 937
- 938 function __construct($host, $port = 22, $timeout = 10)
- 939 {
- 940
- 941
- 942 if (!class_exists('Math_BigInteger')) {
- 943 include_once 'Math/BigInteger.php';
- 944 }
- 945
- 946 if (!function_exists('crypt_random_string')) {
- 947 include_once 'Crypt/Random.php';
- 948 }
- 949
- 950 if (!class_exists('Crypt_Hash')) {
- 951 include_once 'Crypt/Hash.php';
- 952 }
- 953
- 954
- 955 if (!class_exists('Crypt_Base')) {
- 956 include_once 'Crypt/Base.php';
- 957 }
- 958
- 959 $this->message_numbers = array(
- 960 1 => 'NET_SSH2_MSG_DISCONNECT',
- 961 2 => 'NET_SSH2_MSG_IGNORE',
- 962 3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
- 963 4 => 'NET_SSH2_MSG_DEBUG',
- 964 5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
- 965 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
- 966 20 => 'NET_SSH2_MSG_KEXINIT',
- 967 21 => 'NET_SSH2_MSG_NEWKEYS',
- 968 30 => 'NET_SSH2_MSG_KEXDH_INIT',
- 969 31 => 'NET_SSH2_MSG_KEXDH_REPLY',
- 970 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
- 971 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
- 972 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
- 973 53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
- 974
- 975 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
- 976 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
- 977 82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
- 978 90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
- 979 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
- 980 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
- 981 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
- 982 94 => 'NET_SSH2_MSG_CHANNEL_DATA',
- 983 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
- 984 96 => 'NET_SSH2_MSG_CHANNEL_EOF',
- 985 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
- 986 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
- 987 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
- 988 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
- 989 );
- 990 $this->disconnect_reasons = array(
- 991 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
- 992 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
- 993 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
- 994 4 => 'NET_SSH2_DISCONNECT_RESERVED',
- 995 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
- 996 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
- 997 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
- 998 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
- 999 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
- 1000 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
- 1001 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
- 1002 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
- 1003 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
- 1004 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
- 1005 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
- 1006 );
- 1007 $this->channel_open_failure_reasons = array(
- 1008 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
- 1009 );
- 1010 $this->terminal_modes = array(
- 1011 0 => 'NET_SSH2_TTY_OP_END'
- 1012 );
- 1013 $this->channel_extended_data_type_codes = array(
- 1014 1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
- 1015 );
- 1016
- 1017 $this->_define_array(
- 1018 $this->message_numbers,
- 1019 $this->disconnect_reasons,
- 1020 $this->channel_open_failure_reasons,
- 1021 $this->terminal_modes,
- 1022 $this->channel_extended_data_type_codes,
- 1023 array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'),
- 1024 array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'),
- 1025 array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
- 1026 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'),
- 1027
- 1028 array(30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD',
- 1029 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
- 1030 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
- 1031 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
- 1032 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST')
- 1033 );
- 1034
- 1035 if (is_resource($host)) {
- 1036 $this->fsock = $host;
- 1037 return;
- 1038 }
- 1039
- 1040 if (is_string($host)) {
- 1041 $this->host = $host;
- 1042 $this->port = $port;
- 1043 $this->timeout = $timeout;
- 1044 }
- 1045 }
- 1046
- 1047
- 1048
- 1049
- 1050
- 1051
- 1052
- 1053
- 1054
- 1055
- 1056 function Net_SSH2($host, $port = 22, $timeout = 10)
- 1057 {
- 1058 $this->__construct($host, $port, $timeout);
- 1059 }
- 1060
- 1061
- 1062
- 1063
- 1064
- 1065
- 1066
- 1067
- 1068
- 1069
- 1070 function setCryptoEngine($engine)
- 1071 {
- 1072 $this->crypto_engine = $engine;
- 1073 }
- 1074
- 1075
- 1076
- 1077
- 1078
- 1079
- 1080
- 1081
- 1082
- 1083
- 1084 function sendIdentificationStringFirst()
- 1085 {
- 1086 $this->send_id_string_first = true;
- 1087 }
- 1088
- 1089
- 1090
- 1091
- 1092
- 1093
- 1094
- 1095
- 1096
- 1097
- 1098 function sendIdentificationStringLast()
- 1099 {
- 1100 $this->send_id_string_first = false;
- 1101 }
- 1102
- 1103
- 1104
- 1105
- 1106
- 1107
- 1108
- 1109
- 1110
- 1111
- 1112 function sendKEXINITFirst()
- 1113 {
- 1114 $this->send_kex_first = true;
- 1115 }
- 1116
- 1117
- 1118
- 1119
- 1120
- 1121
- 1122
- 1123
- 1124
- 1125
- 1126 function sendKEXINITLast()
- 1127 {
- 1128 $this->send_kex_first = false;
- 1129 }
- 1130
- 1131
- 1132
- 1133
- 1134
- 1135
- 1136
- 1137 function _connect()
- 1138 {
- 1139 if ($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) {
- 1140 return false;
- 1141 }
- 1142
- 1143 $this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
- 1144
- 1145 $this->curTimeout = $this->timeout;
- 1146
- 1147 $this->last_packet = strtok(microtime(), ' ') + strtok('');
- 1148
- 1149 if (!is_resource($this->fsock)) {
- 1150 $start = strtok(microtime(), ' ') + strtok('');
- 1151
- 1152
- 1153
- 1154 $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout);
- 1155 if (!$this->fsock) {
- 1156 $host = $this->host . ':' . $this->port;
- 1157 user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
- 1158 return false;
- 1159 }
- 1160 $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
- 1161
- 1162 $this->curTimeout-= $elapsed;
- 1163
- 1164 if ($this->curTimeout <= 0) {
- 1165 $this->is_timeout = true;
- 1166 return false;
- 1167 }
- 1168 }
- 1169
- 1170 $this->identifier = $this->_generate_identifier();
- 1171
- 1172 if ($this->send_id_string_first) {
- 1173 fputs($this->fsock, $this->identifier . "\r\n");
- 1174 }
- 1175
- 1176
- 1177
- 1178
- 1179
- 1180
- 1181
- 1182
- 1183 $temp = '';
- 1184 $extra = '';
- 1185 while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) {
- 1186 if (substr($temp, -2) == "\r\n") {
- 1187 $extra.= $temp;
- 1188 $temp = '';
- 1189 }
- 1190
- 1191 if ($this->curTimeout) {
- 1192 if ($this->curTimeout < 0) {
- 1193 $this->is_timeout = true;
- 1194 return false;
- 1195 }
- 1196 $read = array($this->fsock);
- 1197 $write = $except = null;
- 1198 $start = strtok(microtime(), ' ') + strtok('');
- 1199 $sec = floor($this->curTimeout);
- 1200 $usec = 1000000 * ($this->curTimeout - $sec);
- 1201
- 1202
- 1203 if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
- 1204 $this->is_timeout = true;
- 1205 return false;
- 1206 }
- 1207 $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
- 1208 $this->curTimeout-= $elapsed;
- 1209 }
- 1210
- 1211 $temp.= fgets($this->fsock, 255);
- 1212 }
- 1213
- 1214 if (feof($this->fsock)) {
- 1215 user_error('Connection closed by server');
- 1216 return false;
- 1217 }
- 1218
- 1219 if (defined('NET_SSH2_LOGGING')) {
- 1220 $this->_append_log('<-', $extra . $temp);
- 1221 $this->_append_log('->', $this->identifier . "\r\n");
- 1222 }
- 1223
- 1224 $this->server_identifier = trim($temp, "\r\n");
- 1225 if (strlen($extra)) {
- 1226 $this->errors[] = utf8_decode($extra);
- 1227 }
- 1228
- 1229 if (version_compare($matches[1], '1.99', '<')) {
- 1230 user_error("Cannot connect to SSH $matches[1] servers");
- 1231 return false;
- 1232 }
- 1233
- 1234 if (!$this->send_id_string_first) {
- 1235 fputs($this->fsock, $this->identifier . "\r\n");
- 1236 }
- 1237
- 1238 if (!$this->send_kex_first) {
- 1239 $response = $this->_get_binary_packet();
- 1240 if ($response === false) {
- 1241 user_error('Connection closed by server');
- 1242 return false;
- 1243 }
- 1244
- 1245 if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
- 1246 user_error('Expected SSH_MSG_KEXINIT');
- 1247 return false;
- 1248 }
- 1249
- 1250 if (!$this->_key_exchange($response)) {
- 1251 return false;
- 1252 }
- 1253 }
- 1254
- 1255 if ($this->send_kex_first && !$this->_key_exchange()) {
- 1256 return false;
- 1257 }
- 1258
- 1259 $this->bitmap|= NET_SSH2_MASK_CONNECTED;
- 1260
- 1261 return true;
- 1262 }
- 1263
- 1264
- 1265
- 1266
- 1267
- 1268
- 1269
- 1270
- 1271
- 1272 function _generate_identifier()
- 1273 {
- 1274 $identifier = 'SSH-2.0-phpseclib_1.0';
- 1275
- 1276 $ext = array();
- 1277 if (extension_loaded('openssl')) {
- 1278 $ext[] = 'openssl';
- 1279 } elseif (extension_loaded('mcrypt')) {
- 1280 $ext[] = 'mcrypt';
- 1281 }
- 1282
- 1283 if (extension_loaded('gmp')) {
- 1284 $ext[] = 'gmp';
- 1285 } elseif (extension_loaded('bcmath')) {
- 1286 $ext[] = 'bcmath';
- 1287 }
- 1288
- 1289 if (!empty($ext)) {
- 1290 $identifier .= ' (' . implode(', ', $ext) . ')';
- 1291 }
- 1292
- 1293 return $identifier;
- 1294 }
- 1295
- 1296
- 1297
- 1298
- 1299
- 1300
- 1301
- 1302 function _key_exchange($kexinit_payload_server = false)
- 1303 {
- 1304 static $kex_algorithms = array(
- 1305 'diffie-hellman-group1-sha1',
- 1306 'diffie-hellman-group14-sha1',
- 1307 'diffie-hellman-group-exchange-sha1',
- 1308 'diffie-hellman-group-exchange-sha256',
- 1309 );
- 1310
- 1311 static $server_host_key_algorithms = array(
- 1312 'ssh-rsa',
- 1313 'ssh-dss'
- 1314 );
- 1315
- 1316 static $encryption_algorithms = false;
- 1317 if ($encryption_algorithms === false) {
- 1318 $encryption_algorithms = array(
- 1319
- 1320 'arcfour256',
- 1321 'arcfour128',
- 1322
- 1323
- 1324
- 1325
- 1326 'aes128-ctr',
- 1327 'aes192-ctr',
- 1328 'aes256-ctr',
- 1329
- 1330 'twofish128-ctr',
- 1331 'twofish192-ctr',
- 1332 'twofish256-ctr',
- 1333
- 1334 'aes128-cbc',
- 1335 'aes192-cbc',
- 1336 'aes256-cbc',
- 1337
- 1338 'twofish128-cbc',
- 1339 'twofish192-cbc',
- 1340 'twofish256-cbc',
- 1341 'twofish-cbc',
- 1342
- 1343
- 1344 'blowfish-ctr',
- 1345
- 1346 'blowfish-cbc',
- 1347
- 1348 '3des-ctr',
- 1349
- 1350 '3des-cbc',
- 1351
- 1352 );
- 1353
- 1354 if (extension_loaded('openssl') && !extension_loaded('mcrypt')) {
- 1355
- 1356
- 1357 $encryption_algorithms = array_diff(
- 1358 $encryption_algorithms,
- 1359 array('arcfour256', 'arcfour128', 'arcfour')
- 1360 );
- 1361 }
- 1362
- 1363 if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) {
- 1364 $encryption_algorithms = array_diff(
- 1365 $encryption_algorithms,
- 1366 array('arcfour256', 'arcfour128', 'arcfour')
- 1367 );
- 1368 }
- 1369 if (phpseclib_resolve_include_path('Crypt/Rijndael.php') === false) {
- 1370 $encryption_algorithms = array_diff(
- 1371 $encryption_algorithms,
- 1372 array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc')
- 1373 );
- 1374 }
- 1375 if (phpseclib_resolve_include_path('Crypt/Twofish.php') === false) {
- 1376 $encryption_algorithms = array_diff(
- 1377 $encryption_algorithms,
- 1378 array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc')
- 1379 );
- 1380 }
- 1381 if (phpseclib_resolve_include_path('Crypt/Blowfish.php') === false) {
- 1382 $encryption_algorithms = array_diff(
- 1383 $encryption_algorithms,
- 1384 array('blowfish-ctr', 'blowfish-cbc')
- 1385 );
- 1386 }
- 1387 if (phpseclib_resolve_include_path('Crypt/TripleDES.php') === false) {
- 1388 $encryption_algorithms = array_diff(
- 1389 $encryption_algorithms,
- 1390 array('3des-ctr', '3des-cbc')
- 1391 );
- 1392 }
- 1393 $encryption_algorithms = array_values($encryption_algorithms);
- 1394 }
- 1395
- 1396 $mac_algorithms = array(
- 1397
- 1398 'hmac-sha2-256',
- 1399
- 1400 'hmac-sha1-96',
- 1401 'hmac-sha1',
- 1402 'hmac-md5-96',
- 1403 'hmac-md5',
- 1404
- 1405 );
- 1406
- 1407 static $compression_algorithms = array(
- 1408 'none'
- 1409
- 1410 );
- 1411
- 1412
- 1413 switch (true) {
- 1414 case $this->server_identifier == 'SSH-2.0-SSHD':
- 1415 case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
- 1416 $mac_algorithms = array_values(array_diff(
- 1417 $mac_algorithms,
- 1418 array('hmac-sha1-96', 'hmac-md5-96')
- 1419 ));
- 1420 }
- 1421
- 1422 static $str_kex_algorithms, $str_server_host_key_algorithms,
- 1423 $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client,
- 1424 $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
- 1425
- 1426 if (empty($str_kex_algorithms)) {
- 1427 $str_kex_algorithms = implode(',', $kex_algorithms);
- 1428 $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
- 1429 $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
- 1430 $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
- 1431 $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
- 1432 }
- 1433
- 1434 $client_cookie = crypt_random_string(16);
- 1435
- 1436 $kexinit_payload_client = pack(
- 1437 'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
- 1438 NET_SSH2_MSG_KEXINIT,
- 1439 $client_cookie,
- 1440 strlen($str_kex_algorithms),
- 1441 $str_kex_algorithms,
- 1442 strlen($str_server_host_key_algorithms),
- 1443 $str_server_host_key_algorithms,
- 1444 strlen($encryption_algorithms_client_to_server),
- 1445 $encryption_algorithms_client_to_server,
- 1446 strlen($encryption_algorithms_server_to_client),
- 1447 $encryption_algorithms_server_to_client,
- 1448 strlen($mac_algorithms_client_to_server),
- 1449 $mac_algorithms_client_to_server,
- 1450 strlen($mac_algorithms_server_to_client),
- 1451 $mac_algorithms_server_to_client,
- 1452 strlen($compression_algorithms_client_to_server),
- 1453 $compression_algorithms_client_to_server,
- 1454 strlen($compression_algorithms_server_to_client),
- 1455 $compression_algorithms_server_to_client,
- 1456 0,
- 1457 '',
- 1458 0,
- 1459 '',
- 1460 0,
- 1461 0
- 1462 );
- 1463
- 1464 if ($this->send_kex_first) {
- 1465 if (!$this->_send_binary_packet($kexinit_payload_client)) {
- 1466 return false;
- 1467 }
- 1468
- 1469 $kexinit_payload_server = $this->_get_binary_packet();
- 1470 if ($kexinit_payload_server === false) {
- 1471 user_error('Connection closed by server');
- 1472 return false;
- 1473 }
- 1474
- 1475 if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
- 1476 user_error('Expected SSH_MSG_KEXINIT');
- 1477 return false;
- 1478 }
- 1479 }
- 1480
- 1481 $response = $kexinit_payload_server;
- 1482 $this->_string_shift($response, 1);
- 1483 $server_cookie = $this->_string_shift($response, 16);
- 1484
- 1485 if (strlen($response) < 4) {
- 1486 return false;
- 1487 }
- 1488 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1489 $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
- 1490
- 1491 if (strlen($response) < 4) {
- 1492 return false;
- 1493 }
- 1494 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1495 $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
- 1496
- 1497 if (strlen($response) < 4) {
- 1498 return false;
- 1499 }
- 1500 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1501 $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
- 1502
- 1503 if (strlen($response) < 4) {
- 1504 return false;
- 1505 }
- 1506 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1507 $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
- 1508
- 1509 if (strlen($response) < 4) {
- 1510 return false;
- 1511 }
- 1512 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1513 $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
- 1514
- 1515 if (strlen($response) < 4) {
- 1516 return false;
- 1517 }
- 1518 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1519 $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
- 1520
- 1521 if (strlen($response) < 4) {
- 1522 return false;
- 1523 }
- 1524 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1525 $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
- 1526
- 1527 if (strlen($response) < 4) {
- 1528 return false;
- 1529 }
- 1530 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1531 $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
- 1532
- 1533 if (strlen($response) < 4) {
- 1534 return false;
- 1535 }
- 1536 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1537 $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
- 1538
- 1539 if (strlen($response) < 4) {
- 1540 return false;
- 1541 }
- 1542 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1543 $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
- 1544
- 1545 if (!strlen($response)) {
- 1546 return false;
- 1547 }
- 1548 extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
- 1549 $first_kex_packet_follows = $first_kex_packet_follows != 0;
- 1550
- 1551 if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) {
- 1552 return false;
- 1553 }
- 1554
- 1555
- 1556
- 1557
- 1558 $decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
- 1559 $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
- 1560 if ($decryptKeyLength === null) {
- 1561 user_error('No compatible server to client encryption algorithms found');
- 1562 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 1563 }
- 1564
- 1565 $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
- 1566 $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
- 1567 if ($encryptKeyLength === null) {
- 1568 user_error('No compatible client to server encryption algorithms found');
- 1569 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 1570 }
- 1571
- 1572 $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
- 1573
- 1574
- 1575 $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
- 1576 if ($kex_algorithm === false) {
- 1577 user_error('No compatible key exchange algorithms found');
- 1578 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 1579 }
- 1580 if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
- 1581 $dh_group_sizes_packed = pack(
- 1582 'NNN',
- 1583 $this->kex_dh_group_size_min,
- 1584 $this->kex_dh_group_size_preferred,
- 1585 $this->kex_dh_group_size_max
- 1586 );
- 1587 $packet = pack(
- 1588 'Ca*',
- 1589 NET_SSH2_MSG_KEXDH_GEX_REQUEST,
- 1590 $dh_group_sizes_packed
- 1591 );
- 1592 if (!$this->_send_binary_packet($packet)) {
- 1593 return false;
- 1594 }
- 1595
- 1596 $response = $this->_get_binary_packet();
- 1597 if ($response === false) {
- 1598 user_error('Connection closed by server');
- 1599 return false;
- 1600 }
- 1601 if (!strlen($response)) {
- 1602 return false;
- 1603 }
- 1604 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 1605 if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
- 1606 user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
- 1607 return false;
- 1608 }
- 1609
- 1610 if (strlen($response) < 4) {
- 1611 return false;
- 1612 }
- 1613 extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
- 1614 $primeBytes = $this->_string_shift($response, $primeLength);
- 1615 $prime = new Math_BigInteger($primeBytes, -256);
- 1616
- 1617 if (strlen($response) < 4) {
- 1618 return false;
- 1619 }
- 1620 extract(unpack('NgLength', $this->_string_shift($response, 4)));
- 1621 $gBytes = $this->_string_shift($response, $gLength);
- 1622 $g = new Math_BigInteger($gBytes, -256);
- 1623
- 1624 $exchange_hash_rfc4419 = pack(
- 1625 'a*Na*Na*',
- 1626 $dh_group_sizes_packed,
- 1627 $primeLength,
- 1628 $primeBytes,
- 1629 $gLength,
- 1630 $gBytes
- 1631 );
- 1632
- 1633 $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
- 1634 $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
- 1635 } else {
- 1636 switch ($kex_algorithm) {
- 1637
- 1638
- 1639 case 'diffie-hellman-group1-sha1':
- 1640 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
- 1641 '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
- 1642 '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
- 1643 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
- 1644 break;
- 1645
- 1646 case 'diffie-hellman-group14-sha1':
- 1647 $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
- 1648 '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
- 1649 '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
- 1650 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
- 1651 '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
- 1652 '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
- 1653 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
- 1654 '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
- 1655 break;
- 1656 }
- 1657
- 1658
- 1659 $g = new Math_BigInteger(2);
- 1660 $prime = new Math_BigInteger($prime, 16);
- 1661 $exchange_hash_rfc4419 = '';
- 1662 $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
- 1663 $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
- 1664 }
- 1665
- 1666 switch ($kex_algorithm) {
- 1667 case 'diffie-hellman-group-exchange-sha256':
- 1668 $kexHash = new Crypt_Hash('sha256');
- 1669 break;
- 1670 default:
- 1671 $kexHash = new Crypt_Hash('sha1');
- 1672 }
- 1673
- 1674
- 1675
- 1676
- 1677
- 1678
- 1679
- 1680
- 1681 $one = new Math_BigInteger(1);
- 1682 $keyLength = min($keyLength, $kexHash->getLength());
- 1683 $max = $one->bitwise_leftShift(16 * $keyLength);
- 1684 $max = $max->subtract($one);
- 1685
- 1686 $x = $one->random($one, $max);
- 1687 $e = $g->modPow($x, $prime);
- 1688
- 1689 $eBytes = $e->toBytes(true);
- 1690 $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
- 1691
- 1692 if (!$this->_send_binary_packet($data)) {
- 1693 user_error('Connection closed by server');
- 1694 return false;
- 1695 }
- 1696
- 1697 $response = $this->_get_binary_packet();
- 1698 if ($response === false) {
- 1699 user_error('Connection closed by server');
- 1700 return false;
- 1701 }
- 1702 if (!strlen($response)) {
- 1703 return false;
- 1704 }
- 1705 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 1706
- 1707 if ($type != $serverKexReplyMessage) {
- 1708 user_error('Expected SSH_MSG_KEXDH_REPLY');
- 1709 return false;
- 1710 }
- 1711
- 1712 if (strlen($response) < 4) {
- 1713 return false;
- 1714 }
- 1715 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1716 $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
- 1717
- 1718 if (strlen($server_public_host_key) < 4) {
- 1719 return false;
- 1720 }
- 1721 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 1722 $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
- 1723
- 1724 if (strlen($response) < 4) {
- 1725 return false;
- 1726 }
- 1727 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1728 $fBytes = $this->_string_shift($response, $temp['length']);
- 1729 $f = new Math_BigInteger($fBytes, -256);
- 1730
- 1731 if (strlen($response) < 4) {
- 1732 return false;
- 1733 }
- 1734 $temp = unpack('Nlength', $this->_string_shift($response, 4));
- 1735 $this->signature = $this->_string_shift($response, $temp['length']);
- 1736
- 1737 if (strlen($this->signature) < 4) {
- 1738 return false;
- 1739 }
- 1740 $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
- 1741 $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
- 1742
- 1743 $key = $f->modPow($x, $prime);
- 1744 $keyBytes = $key->toBytes(true);
- 1745
- 1746 $this->exchange_hash = pack(
- 1747 'Na*Na*Na*Na*Na*a*Na*Na*Na*',
- 1748 strlen($this->identifier),
- 1749 $this->identifier,
- 1750 strlen($this->server_identifier),
- 1751 $this->server_identifier,
- 1752 strlen($kexinit_payload_client),
- 1753 $kexinit_payload_client,
- 1754 strlen($kexinit_payload_server),
- 1755 $kexinit_payload_server,
- 1756 strlen($this->server_public_host_key),
- 1757 $this->server_public_host_key,
- 1758 $exchange_hash_rfc4419,
- 1759 strlen($eBytes),
- 1760 $eBytes,
- 1761 strlen($fBytes),
- 1762 $fBytes,
- 1763 strlen($keyBytes),
- 1764 $keyBytes
- 1765 );
- 1766
- 1767 $this->exchange_hash = $kexHash->hash($this->exchange_hash);
- 1768
- 1769 if ($this->session_id === false) {
- 1770 $this->session_id = $this->exchange_hash;
- 1771 }
- 1772
- 1773 $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
- 1774 if ($server_host_key_algorithm === false) {
- 1775 user_error('No compatible server host key algorithms found');
- 1776 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 1777 }
- 1778
- 1779 if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
- 1780 user_error('Server Host Key Algorithm Mismatch');
- 1781 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 1782 }
- 1783
- 1784 $packet = pack(
- 1785 'C',
- 1786 NET_SSH2_MSG_NEWKEYS
- 1787 );
- 1788
- 1789 if (!$this->_send_binary_packet($packet)) {
- 1790 return false;
- 1791 }
- 1792
- 1793 $response = $this->_get_binary_packet();
- 1794
- 1795 if ($response === false) {
- 1796 user_error('Connection closed by server');
- 1797 return false;
- 1798 }
- 1799
- 1800 if (!strlen($response)) {
- 1801 return false;
- 1802 }
- 1803 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 1804
- 1805 if ($type != NET_SSH2_MSG_NEWKEYS) {
- 1806 user_error('Expected SSH_MSG_NEWKEYS');
- 1807 return false;
- 1808 }
- 1809
- 1810 switch ($encrypt) {
- 1811 case '3des-cbc':
- 1812 if (!class_exists('Crypt_TripleDES')) {
- 1813 include_once 'Crypt/TripleDES.php';
- 1814 }
- 1815 $this->encrypt = new Crypt_TripleDES();
- 1816
- 1817 break;
- 1818 case '3des-ctr':
- 1819 if (!class_exists('Crypt_TripleDES')) {
- 1820 include_once 'Crypt/TripleDES.php';
- 1821 }
- 1822 $this->encrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
- 1823
- 1824 break;
- 1825 case 'aes256-cbc':
- 1826 case 'aes192-cbc':
- 1827 case 'aes128-cbc':
- 1828 if (!class_exists('Crypt_Rijndael')) {
- 1829 include_once 'Crypt/Rijndael.php';
- 1830 }
- 1831 $this->encrypt = new Crypt_Rijndael();
- 1832 $this->encrypt_block_size = 16;
- 1833 break;
- 1834 case 'aes256-ctr':
- 1835 case 'aes192-ctr':
- 1836 case 'aes128-ctr':
- 1837 if (!class_exists('Crypt_Rijndael')) {
- 1838 include_once 'Crypt/Rijndael.php';
- 1839 }
- 1840 $this->encrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR);
- 1841 $this->encrypt_block_size = 16;
- 1842 break;
- 1843 case 'blowfish-cbc':
- 1844 if (!class_exists('Crypt_Blowfish')) {
- 1845 include_once 'Crypt/Blowfish.php';
- 1846 }
- 1847 $this->encrypt = new Crypt_Blowfish();
- 1848 $this->encrypt_block_size = 8;
- 1849 break;
- 1850 case 'blowfish-ctr':
- 1851 if (!class_exists('Crypt_Blowfish')) {
- 1852 include_once 'Crypt/Blowfish.php';
- 1853 }
- 1854 $this->encrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
- 1855 $this->encrypt_block_size = 8;
- 1856 break;
- 1857 case 'twofish128-cbc':
- 1858 case 'twofish192-cbc':
- 1859 case 'twofish256-cbc':
- 1860 case 'twofish-cbc':
- 1861 if (!class_exists('Crypt_Twofish')) {
- 1862 include_once 'Crypt/Twofish.php';
- 1863 }
- 1864 $this->encrypt = new Crypt_Twofish();
- 1865 $this->encrypt_block_size = 16;
- 1866 break;
- 1867 case 'twofish128-ctr':
- 1868 case 'twofish192-ctr':
- 1869 case 'twofish256-ctr':
- 1870 if (!class_exists('Crypt_Twofish')) {
- 1871 include_once 'Crypt/Twofish.php';
- 1872 }
- 1873 $this->encrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
- 1874 $this->encrypt_block_size = 16;
- 1875 break;
- 1876 case 'arcfour':
- 1877 case 'arcfour128':
- 1878 case 'arcfour256':
- 1879 if (!class_exists('Crypt_RC4')) {
- 1880 include_once 'Crypt/RC4.php';
- 1881 }
- 1882 $this->encrypt = new Crypt_RC4();
- 1883 break;
- 1884 case 'none':
- 1885
- 1886 }
- 1887
- 1888 switch ($decrypt) {
- 1889 case '3des-cbc':
- 1890 if (!class_exists('Crypt_TripleDES')) {
- 1891 include_once 'Crypt/TripleDES.php';
- 1892 }
- 1893 $this->decrypt = new Crypt_TripleDES();
- 1894 break;
- 1895 case '3des-ctr':
- 1896 if (!class_exists('Crypt_TripleDES')) {
- 1897 include_once 'Crypt/TripleDES.php';
- 1898 }
- 1899 $this->decrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
- 1900 break;
- 1901 case 'aes256-cbc':
- 1902 case 'aes192-cbc':
- 1903 case 'aes128-cbc':
- 1904 if (!class_exists('Crypt_Rijndael')) {
- 1905 include_once 'Crypt/Rijndael.php';
- 1906 }
- 1907 $this->decrypt = new Crypt_Rijndael();
- 1908 $this->decrypt_block_size = 16;
- 1909 break;
- 1910 case 'aes256-ctr':
- 1911 case 'aes192-ctr':
- 1912 case 'aes128-ctr':
- 1913 if (!class_exists('Crypt_Rijndael')) {
- 1914 include_once 'Crypt/Rijndael.php';
- 1915 }
- 1916 $this->decrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR);
- 1917 $this->decrypt_block_size = 16;
- 1918 break;
- 1919 case 'blowfish-cbc':
- 1920 if (!class_exists('Crypt_Blowfish')) {
- 1921 include_once 'Crypt/Blowfish.php';
- 1922 }
- 1923 $this->decrypt = new Crypt_Blowfish();
- 1924 $this->decrypt_block_size = 8;
- 1925 break;
- 1926 case 'blowfish-ctr':
- 1927 if (!class_exists('Crypt_Blowfish')) {
- 1928 include_once 'Crypt/Blowfish.php';
- 1929 }
- 1930 $this->decrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
- 1931 $this->decrypt_block_size = 8;
- 1932 break;
- 1933 case 'twofish128-cbc':
- 1934 case 'twofish192-cbc':
- 1935 case 'twofish256-cbc':
- 1936 case 'twofish-cbc':
- 1937 if (!class_exists('Crypt_Twofish')) {
- 1938 include_once 'Crypt/Twofish.php';
- 1939 }
- 1940 $this->decrypt = new Crypt_Twofish();
- 1941 $this->decrypt_block_size = 16;
- 1942 break;
- 1943 case 'twofish128-ctr':
- 1944 case 'twofish192-ctr':
- 1945 case 'twofish256-ctr':
- 1946 if (!class_exists('Crypt_Twofish')) {
- 1947 include_once 'Crypt/Twofish.php';
- 1948 }
- 1949 $this->decrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
- 1950 $this->decrypt_block_size = 16;
- 1951 break;
- 1952 case 'arcfour':
- 1953 case 'arcfour128':
- 1954 case 'arcfour256':
- 1955 if (!class_exists('Crypt_RC4')) {
- 1956 include_once 'Crypt/RC4.php';
- 1957 }
- 1958 $this->decrypt = new Crypt_RC4();
- 1959 break;
- 1960 case 'none':
- 1961
- 1962 }
- 1963
- 1964 $this->decrypt_algorithm = $decrypt;
- 1965
- 1966 $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
- 1967
- 1968 if ($this->encrypt) {
- 1969 if ($this->crypto_engine) {
- 1970 $this->encrypt->setEngine($this->crypto_engine);
- 1971 }
- 1972 $this->encrypt->enableContinuousBuffer();
- 1973 $this->encrypt->disablePadding();
- 1974
- 1975 $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
- 1976 while ($this->encrypt_block_size > strlen($iv)) {
- 1977 $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
- 1978 }
- 1979 $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
- 1980
- 1981 $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
- 1982 while ($encryptKeyLength > strlen($key)) {
- 1983 $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
- 1984 }
- 1985 $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
- 1986 }
- 1987
- 1988 if ($this->decrypt) {
- 1989 if ($this->crypto_engine) {
- 1990 $this->decrypt->setEngine($this->crypto_engine);
- 1991 }
- 1992 $this->decrypt->enableContinuousBuffer();
- 1993 $this->decrypt->disablePadding();
- 1994
- 1995 $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
- 1996 while ($this->decrypt_block_size > strlen($iv)) {
- 1997 $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
- 1998 }
- 1999 $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
- 2000
- 2001 $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
- 2002 while ($decryptKeyLength > strlen($key)) {
- 2003 $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
- 2004 }
- 2005 $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
- 2006 }
- 2007
- 2008
- 2009
- 2010
- 2011
- 2012
- 2013
- 2014
- 2015 if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') {
- 2016 $this->encrypt->encrypt(str_repeat("\0", 1536));
- 2017 }
- 2018 if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') {
- 2019 $this->decrypt->decrypt(str_repeat("\0", 1536));
- 2020 }
- 2021
- 2022 $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
- 2023 if ($mac_algorithm === false) {
- 2024 user_error('No compatible client to server message authentication algorithms found');
- 2025 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 2026 }
- 2027
- 2028 $createKeyLength = 0;
- 2029 switch ($mac_algorithm) {
- 2030 case 'hmac-sha2-256':
- 2031 $this->hmac_create = new Crypt_Hash('sha256');
- 2032 $createKeyLength = 32;
- 2033 break;
- 2034 case 'hmac-sha1':
- 2035 $this->hmac_create = new Crypt_Hash('sha1');
- 2036 $createKeyLength = 20;
- 2037 break;
- 2038 case 'hmac-sha1-96':
- 2039 $this->hmac_create = new Crypt_Hash('sha1-96');
- 2040 $createKeyLength = 20;
- 2041 break;
- 2042 case 'hmac-md5':
- 2043 $this->hmac_create = new Crypt_Hash('md5');
- 2044 $createKeyLength = 16;
- 2045 break;
- 2046 case 'hmac-md5-96':
- 2047 $this->hmac_create = new Crypt_Hash('md5-96');
- 2048 $createKeyLength = 16;
- 2049 }
- 2050
- 2051 $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
- 2052 if ($mac_algorithm === false) {
- 2053 user_error('No compatible server to client message authentication algorithms found');
- 2054 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 2055 }
- 2056
- 2057 $checkKeyLength = 0;
- 2058 $this->hmac_size = 0;
- 2059 switch ($mac_algorithm) {
- 2060 case 'hmac-sha2-256':
- 2061 $this->hmac_check = new Crypt_Hash('sha256');
- 2062 $checkKeyLength = 32;
- 2063 $this->hmac_size = 32;
- 2064 break;
- 2065 case 'hmac-sha1':
- 2066 $this->hmac_check = new Crypt_Hash('sha1');
- 2067 $checkKeyLength = 20;
- 2068 $this->hmac_size = 20;
- 2069 break;
- 2070 case 'hmac-sha1-96':
- 2071 $this->hmac_check = new Crypt_Hash('sha1-96');
- 2072 $checkKeyLength = 20;
- 2073 $this->hmac_size = 12;
- 2074 break;
- 2075 case 'hmac-md5':
- 2076 $this->hmac_check = new Crypt_Hash('md5');
- 2077 $checkKeyLength = 16;
- 2078 $this->hmac_size = 16;
- 2079 break;
- 2080 case 'hmac-md5-96':
- 2081 $this->hmac_check = new Crypt_Hash('md5-96');
- 2082 $checkKeyLength = 16;
- 2083 $this->hmac_size = 12;
- 2084 }
- 2085
- 2086 $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
- 2087 while ($createKeyLength > strlen($key)) {
- 2088 $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
- 2089 }
- 2090 $this->hmac_create->setKey(substr($key, 0, $createKeyLength));
- 2091
- 2092 $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id);
- 2093 while ($checkKeyLength > strlen($key)) {
- 2094 $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
- 2095 }
- 2096 $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
- 2097
- 2098 $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
- 2099 if ($compression_algorithm === false) {
- 2100 user_error('No compatible server to client compression algorithms found');
- 2101 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 2102 }
- 2103 $this->decompress = $compression_algorithm == 'zlib';
- 2104
- 2105 $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
- 2106 if ($compression_algorithm === false) {
- 2107 user_error('No compatible client to server compression algorithms found');
- 2108 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 2109 }
- 2110 $this->compress = $compression_algorithm == 'zlib';
- 2111
- 2112 return true;
- 2113 }
- 2114
- 2115
- 2116
- 2117
- 2118
- 2119
- 2120
- 2121
- 2122 function _encryption_algorithm_to_key_size($algorithm)
- 2123 {
- 2124 if ($this->bad_key_size_fix && $this->_bad_algorithm_candidate($algorithm)) {
- 2125 return 16;
- 2126 }
- 2127
- 2128 switch ($algorithm) {
- 2129 case 'none':
- 2130 return 0;
- 2131 case 'aes128-cbc':
- 2132 case 'aes128-ctr':
- 2133 case 'arcfour':
- 2134 case 'arcfour128':
- 2135 case 'blowfish-cbc':
- 2136 case 'blowfish-ctr':
- 2137 case 'twofish128-cbc':
- 2138 case 'twofish128-ctr':
- 2139 return 16;
- 2140 case '3des-cbc':
- 2141 case '3des-ctr':
- 2142 case 'aes192-cbc':
- 2143 case 'aes192-ctr':
- 2144 case 'twofish192-cbc':
- 2145 case 'twofish192-ctr':
- 2146 return 24;
- 2147 case 'aes256-cbc':
- 2148 case 'aes256-ctr':
- 2149 case 'arcfour256':
- 2150 case 'twofish-cbc':
- 2151 case 'twofish256-cbc':
- 2152 case 'twofish256-ctr':
- 2153 return 32;
- 2154 }
- 2155 return null;
- 2156 }
- 2157
- 2158
- 2159
- 2160
- 2161
- 2162
- 2163
- 2164
- 2165
- 2166
- 2167 function _bad_algorithm_candidate($algorithm)
- 2168 {
- 2169 switch ($algorithm) {
- 2170 case 'arcfour256':
- 2171 case 'aes192-ctr':
- 2172 case 'aes256-ctr':
- 2173 return true;
- 2174 }
- 2175
- 2176 return false;
- 2177 }
- 2178
- 2179
- 2180
- 2181
- 2182
- 2183
- 2184
- 2185
- 2186
- 2187
- 2188
- 2189
- 2190
- 2191 function login($username)
- 2192 {
- 2193 $args = func_get_args();
- 2194 return call_user_func_array(array(&$this, '_login'), $args);
- 2195 }
- 2196
- 2197
- 2198
- 2199
- 2200
- 2201
- 2202
- 2203
- 2204
- 2205
- 2206
- 2207 function _login($username)
- 2208 {
- 2209 if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
- 2210 if (!$this->_connect()) {
- 2211 return false;
- 2212 }
- 2213 }
- 2214
- 2215 $args = array_slice(func_get_args(), 1);
- 2216 if (empty($args)) {
- 2217 return $this->_login_helper($username);
- 2218 }
- 2219
- 2220 foreach ($args as $arg) {
- 2221 if ($this->_login_helper($username, $arg)) {
- 2222 return true;
- 2223 }
- 2224 }
- 2225 return false;
- 2226 }
- 2227
- 2228
- 2229
- 2230
- 2231
- 2232
- 2233
- 2234
- 2235
- 2236
- 2237
- 2238 function _login_helper($username, $password = null)
- 2239 {
- 2240 if (!($this->bitmap & NET_SSH2_MASK_CONNECTED)) {
- 2241 return false;
- 2242 }
- 2243
- 2244 if (!($this->bitmap & NET_SSH2_MASK_LOGIN_REQ)) {
- 2245 $packet = pack(
- 2246 'CNa*',
- 2247 NET_SSH2_MSG_SERVICE_REQUEST,
- 2248 strlen('ssh-userauth'),
- 2249 'ssh-userauth'
- 2250 );
- 2251
- 2252 if (!$this->_send_binary_packet($packet)) {
- 2253 return false;
- 2254 }
- 2255
- 2256 $response = $this->_get_binary_packet();
- 2257 if ($response === false) {
- 2258 if ($this->retry_connect) {
- 2259 $this->retry_connect = false;
- 2260 if (!$this->_connect()) {
- 2261 return false;
- 2262 }
- 2263 return $this->_login_helper($username, $password);
- 2264 }
- 2265 user_error('Connection closed by server');
- 2266 return false;
- 2267 }
- 2268
- 2269 if (strlen($response) < 4) {
- 2270 return false;
- 2271 }
- 2272 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 2273
- 2274 if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
- 2275 user_error('Expected SSH_MSG_SERVICE_ACCEPT');
- 2276 return false;
- 2277 }
- 2278 $this->bitmap |= NET_SSH2_MASK_LOGIN_REQ;
- 2279 }
- 2280
- 2281 if (strlen($this->last_interactive_response)) {
- 2282 return !is_string($password) && !is_array($password) ? false : $this->_keyboard_interactive_process($password);
- 2283 }
- 2284
- 2285
- 2286 if (is_object($password)) {
- 2287 switch (strtolower(get_class($password))) {
- 2288 case 'crypt_rsa':
- 2289 return $this->_privatekey_login($username, $password);
- 2290 case 'system_ssh_agent':
- 2291 return $this->_ssh_agent_login($username, $password);
- 2292 }
- 2293 }
- 2294
- 2295 if (is_array($password)) {
- 2296 if ($this->_keyboard_interactive_login($username, $password)) {
- 2297 $this->bitmap |= NET_SSH2_MASK_LOGIN;
- 2298 return true;
- 2299 }
- 2300 return false;
- 2301 }
- 2302
- 2303 if (!isset($password)) {
- 2304 $packet = pack(
- 2305 'CNa*Na*Na*',
- 2306 NET_SSH2_MSG_USERAUTH_REQUEST,
- 2307 strlen($username),
- 2308 $username,
- 2309 strlen('ssh-connection'),
- 2310 'ssh-connection',
- 2311 strlen('none'),
- 2312 'none'
- 2313 );
- 2314
- 2315 if (!$this->_send_binary_packet($packet)) {
- 2316 return false;
- 2317 }
- 2318
- 2319 $response = $this->_get_binary_packet();
- 2320 if ($response === false) {
- 2321 user_error('Connection closed by server');
- 2322 return false;
- 2323 }
- 2324
- 2325 if (!strlen($response)) {
- 2326 return false;
- 2327 }
- 2328 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 2329
- 2330 switch ($type) {
- 2331 case NET_SSH2_MSG_USERAUTH_SUCCESS:
- 2332 $this->bitmap |= NET_SSH2_MASK_LOGIN;
- 2333 return true;
- 2334
- 2335 default:
- 2336 return false;
- 2337 }
- 2338 }
- 2339
- 2340 $packet = pack(
- 2341 'CNa*Na*Na*CNa*',
- 2342 NET_SSH2_MSG_USERAUTH_REQUEST,
- 2343 strlen($username),
- 2344 $username,
- 2345 strlen('ssh-connection'),
- 2346 'ssh-connection',
- 2347 strlen('password'),
- 2348 'password',
- 2349 0,
- 2350 strlen($password),
- 2351 $password
- 2352 );
- 2353
- 2354
- 2355 if (!defined('NET_SSH2_LOGGING')) {
- 2356 $logged = null;
- 2357 } else {
- 2358 $logged = pack(
- 2359 'CNa*Na*Na*CNa*',
- 2360 NET_SSH2_MSG_USERAUTH_REQUEST,
- 2361 strlen('username'),
- 2362 'username',
- 2363 strlen('ssh-connection'),
- 2364 'ssh-connection',
- 2365 strlen('password'),
- 2366 'password',
- 2367 0,
- 2368 strlen('password'),
- 2369 'password'
- 2370 );
- 2371 }
- 2372
- 2373 if (!$this->_send_binary_packet($packet, $logged)) {
- 2374 return false;
- 2375 }
- 2376
- 2377 $response = $this->_get_binary_packet();
- 2378 if ($response === false) {
- 2379 user_error('Connection closed by server');
- 2380 return false;
- 2381 }
- 2382
- 2383 if (!strlen($response)) {
- 2384 return false;
- 2385 }
- 2386 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 2387
- 2388 switch ($type) {
- 2389 case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ:
- 2390 if (defined('NET_SSH2_LOGGING')) {
- 2391 $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ';
- 2392 }
- 2393 if (strlen($response) < 4) {
- 2394 return false;
- 2395 }
- 2396 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2397 $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . utf8_decode($this->_string_shift($response, $length));
- 2398 return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
- 2399 case NET_SSH2_MSG_USERAUTH_FAILURE:
- 2400
- 2401
- 2402 if (strlen($response) < 4) {
- 2403 return false;
- 2404 }
- 2405 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2406 $auth_methods = explode(',', $this->_string_shift($response, $length));
- 2407 if (!strlen($response)) {
- 2408 return false;
- 2409 }
- 2410 extract(unpack('Cpartial_success', $this->_string_shift($response, 1)));
- 2411 $partial_success = $partial_success != 0;
- 2412
- 2413 if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) {
- 2414 if ($this->_keyboard_interactive_login($username, $password)) {
- 2415 $this->bitmap |= NET_SSH2_MASK_LOGIN;
- 2416 return true;
- 2417 }
- 2418 return false;
- 2419 }
- 2420 return false;
- 2421 case NET_SSH2_MSG_USERAUTH_SUCCESS:
- 2422 $this->bitmap |= NET_SSH2_MASK_LOGIN;
- 2423 return true;
- 2424 }
- 2425
- 2426 return false;
- 2427 }
- 2428
- 2429
- 2430
- 2431
- 2432
- 2433
- 2434
- 2435
- 2436
- 2437
- 2438
- 2439 function _keyboard_interactive_login($username, $password)
- 2440 {
- 2441 $packet = pack(
- 2442 'CNa*Na*Na*Na*Na*',
- 2443 NET_SSH2_MSG_USERAUTH_REQUEST,
- 2444 strlen($username),
- 2445 $username,
- 2446 strlen('ssh-connection'),
- 2447 'ssh-connection',
- 2448 strlen('keyboard-interactive'),
- 2449 'keyboard-interactive',
- 2450 0,
- 2451 '',
- 2452 0,
- 2453 ''
- 2454 );
- 2455
- 2456 if (!$this->_send_binary_packet($packet)) {
- 2457 return false;
- 2458 }
- 2459
- 2460 return $this->_keyboard_interactive_process($password);
- 2461 }
- 2462
- 2463
- 2464
- 2465
- 2466
- 2467
- 2468
- 2469
- 2470 function _keyboard_interactive_process()
- 2471 {
- 2472 $responses = func_get_args();
- 2473
- 2474 if (strlen($this->last_interactive_response)) {
- 2475 $response = $this->last_interactive_response;
- 2476 } else {
- 2477 $orig = $response = $this->_get_binary_packet();
- 2478 if ($response === false) {
- 2479 user_error('Connection closed by server');
- 2480 return false;
- 2481 }
- 2482 }
- 2483
- 2484 if (!strlen($response)) {
- 2485 return false;
- 2486 }
- 2487 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 2488
- 2489 switch ($type) {
- 2490 case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
- 2491 if (strlen($response) < 4) {
- 2492 return false;
- 2493 }
- 2494 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2495 $this->_string_shift($response, $length);
- 2496 if (strlen($response) < 4) {
- 2497 return false;
- 2498 }
- 2499 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2500 $this->_string_shift($response, $length);
- 2501 if (strlen($response) < 4) {
- 2502 return false;
- 2503 }
- 2504 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2505 $this->_string_shift($response, $length);
- 2506 if (strlen($response) < 4) {
- 2507 return false;
- 2508 }
- 2509 extract(unpack('Nnum_prompts', $this->_string_shift($response, 4)));
- 2510
- 2511 for ($i = 0; $i < count($responses); $i++) {
- 2512 if (is_array($responses[$i])) {
- 2513 foreach ($responses[$i] as $key => $value) {
- 2514 $this->keyboard_requests_responses[$key] = $value;
- 2515 }
- 2516 unset($responses[$i]);
- 2517 }
- 2518 }
- 2519 $responses = array_values($responses);
- 2520
- 2521 if (isset($this->keyboard_requests_responses)) {
- 2522 for ($i = 0; $i < $num_prompts; $i++) {
- 2523 if (strlen($response) < 4) {
- 2524 return false;
- 2525 }
- 2526 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2527
- 2528 $prompt = $this->_string_shift($response, $length);
- 2529
- 2530 foreach ($this->keyboard_requests_responses as $key => $value) {
- 2531 if (substr($prompt, 0, strlen($key)) == $key) {
- 2532 $responses[] = $value;
- 2533 break;
- 2534 }
- 2535 }
- 2536 }
- 2537 }
- 2538
- 2539
- 2540 if (strlen($this->last_interactive_response)) {
- 2541 $this->last_interactive_response = '';
- 2542 } elseif (defined('NET_SSH2_LOGGING')) {
- 2543 $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
- 2544 'UNKNOWN',
- 2545 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
- 2546 $this->message_number_log[count($this->message_number_log) - 1]
- 2547 );
- 2548 }
- 2549
- 2550 if (!count($responses) && $num_prompts) {
- 2551 $this->last_interactive_response = $orig;
- 2552 return false;
- 2553 }
- 2554
- 2555
- 2556
- 2557
- 2558
- 2559
- 2560 $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses));
- 2561 for ($i = 0; $i < count($responses); $i++) {
- 2562 $packet.= pack('Na*', strlen($responses[$i]), $responses[$i]);
- 2563 $logged.= pack('Na*', strlen('dummy-answer'), 'dummy-answer');
- 2564 }
- 2565
- 2566 if (!$this->_send_binary_packet($packet, $logged)) {
- 2567 return false;
- 2568 }
- 2569
- 2570 if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) {
- 2571 $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
- 2572 'UNKNOWN',
- 2573 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE',
- 2574 $this->message_number_log[count($this->message_number_log) - 1]
- 2575 );
- 2576 }
- 2577
- 2578
- 2579
- 2580
- 2581
- 2582
- 2583
- 2584
- 2585 return $this->_keyboard_interactive_process();
- 2586 case NET_SSH2_MSG_USERAUTH_SUCCESS:
- 2587 return true;
- 2588 case NET_SSH2_MSG_USERAUTH_FAILURE:
- 2589 return false;
- 2590 }
- 2591
- 2592 return false;
- 2593 }
- 2594
- 2595
- 2596
- 2597
- 2598
- 2599
- 2600
- 2601
- 2602
- 2603 function _ssh_agent_login($username, $agent)
- 2604 {
- 2605 $this->agent = $agent;
- 2606 $keys = $agent->requestIdentities();
- 2607 foreach ($keys as $key) {
- 2608 if ($this->_privatekey_login($username, $key)) {
- 2609 return true;
- 2610 }
- 2611 }
- 2612
- 2613 return false;
- 2614 }
- 2615
- 2616
- 2617
- 2618
- 2619
- 2620
- 2621
- 2622
- 2623
- 2624
- 2625
- 2626 function _privatekey_login($username, $privatekey)
- 2627 {
- 2628
- 2629 $publickey = $privatekey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_RAW);
- 2630 if ($publickey === false) {
- 2631 return false;
- 2632 }
- 2633
- 2634 $publickey = array(
- 2635 'e' => $publickey['e']->toBytes(true),
- 2636 'n' => $publickey['n']->toBytes(true)
- 2637 );
- 2638 $publickey = pack(
- 2639 'Na*Na*Na*',
- 2640 strlen('ssh-rsa'),
- 2641 'ssh-rsa',
- 2642 strlen($publickey['e']),
- 2643 $publickey['e'],
- 2644 strlen($publickey['n']),
- 2645 $publickey['n']
- 2646 );
- 2647
- 2648 $part1 = pack(
- 2649 'CNa*Na*Na*',
- 2650 NET_SSH2_MSG_USERAUTH_REQUEST,
- 2651 strlen($username),
- 2652 $username,
- 2653 strlen('ssh-connection'),
- 2654 'ssh-connection',
- 2655 strlen('publickey'),
- 2656 'publickey'
- 2657 );
- 2658 $part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey);
- 2659
- 2660 $packet = $part1 . chr(0) . $part2;
- 2661 if (!$this->_send_binary_packet($packet)) {
- 2662 return false;
- 2663 }
- 2664
- 2665 $response = $this->_get_binary_packet();
- 2666 if ($response === false) {
- 2667 user_error('Connection closed by server');
- 2668 return false;
- 2669 }
- 2670
- 2671 if (!strlen($response)) {
- 2672 return false;
- 2673 }
- 2674 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 2675
- 2676 switch ($type) {
- 2677 case NET_SSH2_MSG_USERAUTH_FAILURE:
- 2678 if (strlen($response) < 4) {
- 2679 return false;
- 2680 }
- 2681 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 2682 $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
- 2683 return false;
- 2684 case NET_SSH2_MSG_USERAUTH_PK_OK:
- 2685
- 2686
- 2687 if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) {
- 2688 $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
- 2689 'UNKNOWN',
- 2690 'NET_SSH2_MSG_USERAUTH_PK_OK',
- 2691 $this->message_number_log[count($this->message_number_log) - 1]
- 2692 );
- 2693 }
- 2694 }
- 2695
- 2696 $packet = $part1 . chr(1) . $part2;
- 2697 $privatekey->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
- 2698 $signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet));
- 2699 $signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature);
- 2700 $packet.= pack('Na*', strlen($signature), $signature);
- 2701
- 2702 if (!$this->_send_binary_packet($packet)) {
- 2703 return false;
- 2704 }
- 2705
- 2706 $response = $this->_get_binary_packet();
- 2707 if ($response === false) {
- 2708 user_error('Connection closed by server');
- 2709 return false;
- 2710 }
- 2711
- 2712 if (!strlen($response)) {
- 2713 return false;
- 2714 }
- 2715 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 2716
- 2717 switch ($type) {
- 2718 case NET_SSH2_MSG_USERAUTH_FAILURE:
- 2719
- 2720 return false;
- 2721 case NET_SSH2_MSG_USERAUTH_SUCCESS:
- 2722 $this->bitmap |= NET_SSH2_MASK_LOGIN;
- 2723 return true;
- 2724 }
- 2725
- 2726 return false;
- 2727 }
- 2728
- 2729
- 2730
- 2731
- 2732
- 2733
- 2734
- 2735
- 2736
- 2737
- 2738 function setTimeout($timeout)
- 2739 {
- 2740 $this->timeout = $this->curTimeout = $timeout;
- 2741 }
- 2742
- 2743
- 2744
- 2745
- 2746
- 2747
- 2748 function getStdError()
- 2749 {
- 2750 return $this->stdErrorLog;
- 2751 }
- 2752
- 2753
- 2754
- 2755
- 2756
- 2757
- 2758
- 2759
- 2760
- 2761
- 2762
- 2763
- 2764 function exec($command, $callback = null)
- 2765 {
- 2766 $this->curTimeout = $this->timeout;
- 2767 $this->is_timeout = false;
- 2768 $this->stdErrorLog = '';
- 2769
- 2770 if (!$this->isAuthenticated()) {
- 2771 return false;
- 2772 }
- 2773
- 2774 if ($this->in_request_pty_exec) {
- 2775 user_error('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
- 2776 return false;
- 2777 }
- 2778
- 2779
- 2780
- 2781
- 2782
- 2783 $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = $this->window_size;
- 2784
- 2785
- 2786 $packet_size = 0x4000;
- 2787
- 2788 $packet = pack(
- 2789 'CNa*N3',
- 2790 NET_SSH2_MSG_CHANNEL_OPEN,
- 2791 strlen('session'),
- 2792 'session',
- 2793 NET_SSH2_CHANNEL_EXEC,
- 2794 $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC],
- 2795 $packet_size
- 2796 );
- 2797
- 2798 if (!$this->_send_binary_packet($packet)) {
- 2799 return false;
- 2800 }
- 2801
- 2802 $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
- 2803
- 2804 $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
- 2805 if ($response === false) {
- 2806 return false;
- 2807 }
- 2808
- 2809 if ($this->request_pty === true) {
- 2810 $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
- 2811 $packet = pack(
- 2812 'CNNa*CNa*N5a*',
- 2813 NET_SSH2_MSG_CHANNEL_REQUEST,
- 2814 $this->server_channels[NET_SSH2_CHANNEL_EXEC],
- 2815 strlen('pty-req'),
- 2816 'pty-req',
- 2817 1,
- 2818 strlen('vt100'),
- 2819 'vt100',
- 2820 $this->windowColumns,
- 2821 $this->windowRows,
- 2822 0,
- 2823 0,
- 2824 strlen($terminal_modes),
- 2825 $terminal_modes
- 2826 );
- 2827
- 2828 if (!$this->_send_binary_packet($packet)) {
- 2829 return false;
- 2830 }
- 2831
- 2832 $response = $this->_get_binary_packet();
- 2833 if ($response === false) {
- 2834 user_error('Connection closed by server');
- 2835 return false;
- 2836 }
- 2837
- 2838 if (!strlen($response)) {
- 2839 return false;
- 2840 }
- 2841 list(, $type) = unpack('C', $this->_string_shift($response, 1));
- 2842
- 2843 switch ($type) {
- 2844 case NET_SSH2_MSG_CHANNEL_SUCCESS:
- 2845 break;
- 2846 case NET_SSH2_MSG_CHANNEL_FAILURE:
- 2847 default:
- 2848 user_error('Unable to request pseudo-terminal');
- 2849 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 2850 }
- 2851 $this->in_request_pty_exec = true;
- 2852 }
- 2853
- 2854
- 2855
- 2856
- 2857
- 2858
- 2859
- 2860
- 2861
- 2862
- 2863 $packet = pack(
- 2864 'CNNa*CNa*',
- 2865 NET_SSH2_MSG_CHANNEL_REQUEST,
- 2866 $this->server_channels[NET_SSH2_CHANNEL_EXEC],
- 2867 strlen('exec'),
- 2868 'exec',
- 2869 1,
- 2870 strlen($command),
- 2871 $command
- 2872 );
- 2873
- 2874 if (!$this->_send_binary_packet($packet)) {
- 2875 return false;
- 2876 }
- 2877
- 2878 $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
- 2879
- 2880 $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
- 2881 if ($response === false) {
- 2882 return false;
- 2883 }
- 2884
- 2885 $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
- 2886
- 2887 if ($callback === false || $this->in_request_pty_exec) {
- 2888 return true;
- 2889 }
- 2890
- 2891 $output = '';
- 2892 while (true) {
- 2893 $temp = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
- 2894 switch (true) {
- 2895 case $temp === true:
- 2896 return is_callable($callback) ? true : $output;
- 2897 case $temp === false:
- 2898 return false;
- 2899 default:
- 2900 if (is_callable($callback)) {
- 2901 if (call_user_func($callback, $temp) === true) {
- 2902 $this->_close_channel(NET_SSH2_CHANNEL_EXEC);
- 2903 return true;
- 2904 }
- 2905 } else {
- 2906 $output.= $temp;
- 2907 }
- 2908 }
- 2909 }
- 2910 }
- 2911
- 2912
- 2913
- 2914
- 2915
- 2916
- 2917
- 2918
- 2919
- 2920 function _initShell()
- 2921 {
- 2922 if ($this->in_request_pty_exec === true) {
- 2923 return true;
- 2924 }
- 2925
- 2926 $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = $this->window_size;
- 2927 $packet_size = 0x4000;
- 2928
- 2929 $packet = pack(
- 2930 'CNa*N3',
- 2931 NET_SSH2_MSG_CHANNEL_OPEN,
- 2932 strlen('session'),
- 2933 'session',
- 2934 NET_SSH2_CHANNEL_SHELL,
- 2935 $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL],
- 2936 $packet_size
- 2937 );
- 2938
- 2939 if (!$this->_send_binary_packet($packet)) {
- 2940 return false;
- 2941 }
- 2942
- 2943 $this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
- 2944
- 2945 $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL);
- 2946 if ($response === false) {
- 2947 return false;
- 2948 }
- 2949
- 2950 $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
- 2951 $packet = pack(
- 2952 'CNNa*CNa*N5a*',
- 2953 NET_SSH2_MSG_CHANNEL_REQUEST,
- 2954 $this->server_channels[NET_SSH2_CHANNEL_SHELL],
- 2955 strlen('pty-req'),
- 2956 'pty-req',
- 2957 1,
- 2958 strlen('vt100'),
- 2959 'vt100',
- 2960 $this->windowColumns,
- 2961 $this->windowRows,
- 2962 0,
- 2963 0,
- 2964 strlen($terminal_modes),
- 2965 $terminal_modes
- 2966 );
- 2967
- 2968 if (!$this->_send_binary_packet($packet)) {
- 2969 return false;
- 2970 }
- 2971
- 2972 $response = $this->_get_binary_packet();
- 2973 if ($response === false) {
- 2974 user_error('Connection closed by server');
- 2975 return false;
- 2976 }
- 2977
- 2978 if (!strlen($response)) {
- 2979 return false;
- 2980 }
- 2981 list(, $type) = unpack('C', $this->_string_shift($response, 1));
- 2982
- 2983 switch ($type) {
- 2984 case NET_SSH2_MSG_CHANNEL_SUCCESS:
- 2985
- 2986 case NET_SSH2_MSG_CHANNEL_FAILURE:
- 2987 break;
- 2988 default:
- 2989 user_error('Unable to request pseudo-terminal');
- 2990 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 2991 }
- 2992
- 2993 $packet = pack(
- 2994 'CNNa*C',
- 2995 NET_SSH2_MSG_CHANNEL_REQUEST,
- 2996 $this->server_channels[NET_SSH2_CHANNEL_SHELL],
- 2997 strlen('shell'),
- 2998 'shell',
- 2999 1
- 3000 );
- 3001 if (!$this->_send_binary_packet($packet)) {
- 3002 return false;
- 3003 }
- 3004
- 3005 $this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
- 3006
- 3007 $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL);
- 3008 if ($response === false) {
- 3009 return false;
- 3010 }
- 3011
- 3012 $this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
- 3013
- 3014 $this->bitmap |= NET_SSH2_MASK_SHELL;
- 3015
- 3016 return true;
- 3017 }
- 3018
- 3019
- 3020
- 3021
- 3022
- 3023
- 3024
- 3025
- 3026
- 3027 function _get_interactive_channel()
- 3028 {
- 3029 switch (true) {
- 3030 case $this->in_subsystem:
- 3031 return NET_SSH2_CHANNEL_SUBSYSTEM;
- 3032 case $this->in_request_pty_exec:
- 3033 return NET_SSH2_CHANNEL_EXEC;
- 3034 default:
- 3035 return NET_SSH2_CHANNEL_SHELL;
- 3036 }
- 3037 }
- 3038
- 3039
- 3040
- 3041
- 3042
- 3043
- 3044
- 3045 function _get_open_channel()
- 3046 {
- 3047 $channel = NET_SSH2_CHANNEL_EXEC;
- 3048 do {
- 3049 if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) {
- 3050 return $channel;
- 3051 }
- 3052 } while ($channel++ < NET_SSH2_CHANNEL_SUBSYSTEM);
- 3053
- 3054 return false;
- 3055 }
- 3056
- 3057
- 3058
- 3059
- 3060
- 3061
- 3062
- 3063
- 3064
- 3065
- 3066
- 3067
- 3068
- 3069 function read($expect = '', $mode = NET_SSH2_READ_SIMPLE)
- 3070 {
- 3071 $this->curTimeout = $this->timeout;
- 3072 $this->is_timeout = false;
- 3073
- 3074 if (!$this->isAuthenticated()) {
- 3075 user_error('Operation disallowed prior to login()');
- 3076 return false;
- 3077 }
- 3078
- 3079 if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) {
- 3080 user_error('Unable to initiate an interactive shell session');
- 3081 return false;
- 3082 }
- 3083
- 3084 $channel = $this->_get_interactive_channel();
- 3085
- 3086 if ($mode == NET_SSH2_READ_NEXT) {
- 3087 return $this->_get_channel_packet($channel);
- 3088 }
- 3089
- 3090 $match = $expect;
- 3091 while (true) {
- 3092 if ($mode == NET_SSH2_READ_REGEX) {
- 3093 preg_match($expect, substr($this->interactiveBuffer, -1024), $matches);
- 3094 $match = isset($matches[0]) ? $matches[0] : '';
- 3095 }
- 3096 $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
- 3097 if ($pos !== false) {
- 3098 return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
- 3099 }
- 3100 $response = $this->_get_channel_packet($channel);
- 3101 if (is_bool($response)) {
- 3102 $this->in_request_pty_exec = false;
- 3103 return $response ? $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer)) : false;
- 3104 }
- 3105
- 3106 $this->interactiveBuffer.= $response;
- 3107 }
- 3108 }
- 3109
- 3110
- 3111
- 3112
- 3113
- 3114
- 3115
- 3116
- 3117
- 3118 function write($cmd)
- 3119 {
- 3120 if (!$this->isAuthenticated()) {
- 3121 user_error('Operation disallowed prior to login()');
- 3122 return false;
- 3123 }
- 3124
- 3125 if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) {
- 3126 user_error('Unable to initiate an interactive shell session');
- 3127 return false;
- 3128 }
- 3129
- 3130 return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd);
- 3131 }
- 3132
- 3133
- 3134
- 3135
- 3136
- 3137
- 3138
- 3139
- 3140
- 3141
- 3142
- 3143
- 3144
- 3145
- 3146
- 3147 function startSubsystem($subsystem)
- 3148 {
- 3149 $this->window_size_server_to_client[NET_SSH2_CHANNEL_SUBSYSTEM] = $this->window_size;
- 3150
- 3151 $packet = pack(
- 3152 'CNa*N3',
- 3153 NET_SSH2_MSG_CHANNEL_OPEN,
- 3154 strlen('session'),
- 3155 'session',
- 3156 NET_SSH2_CHANNEL_SUBSYSTEM,
- 3157 $this->window_size,
- 3158 0x4000
- 3159 );
- 3160
- 3161 if (!$this->_send_binary_packet($packet)) {
- 3162 return false;
- 3163 }
- 3164
- 3165 $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
- 3166
- 3167 $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM);
- 3168 if ($response === false) {
- 3169 return false;
- 3170 }
- 3171
- 3172 $packet = pack(
- 3173 'CNNa*CNa*',
- 3174 NET_SSH2_MSG_CHANNEL_REQUEST,
- 3175 $this->server_channels[NET_SSH2_CHANNEL_SUBSYSTEM],
- 3176 strlen('subsystem'),
- 3177 'subsystem',
- 3178 1,
- 3179 strlen($subsystem),
- 3180 $subsystem
- 3181 );
- 3182 if (!$this->_send_binary_packet($packet)) {
- 3183 return false;
- 3184 }
- 3185
- 3186 $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
- 3187
- 3188 $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM);
- 3189
- 3190 if ($response === false) {
- 3191 return false;
- 3192 }
- 3193
- 3194 $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
- 3195
- 3196 $this->bitmap |= NET_SSH2_MASK_SHELL;
- 3197 $this->in_subsystem = true;
- 3198
- 3199 return true;
- 3200 }
- 3201
- 3202
- 3203
- 3204
- 3205
- 3206
- 3207
- 3208
- 3209 function stopSubsystem()
- 3210 {
- 3211 $this->in_subsystem = false;
- 3212 $this->_close_channel(NET_SSH2_CHANNEL_SUBSYSTEM);
- 3213 return true;
- 3214 }
- 3215
- 3216
- 3217
- 3218
- 3219
- 3220
- 3221
- 3222
- 3223 function reset()
- 3224 {
- 3225 $this->_close_channel($this->_get_interactive_channel());
- 3226 }
- 3227
- 3228
- 3229
- 3230
- 3231
- 3232
- 3233
- 3234
- 3235 function isTimeout()
- 3236 {
- 3237 return $this->is_timeout;
- 3238 }
- 3239
- 3240
- 3241
- 3242
- 3243
- 3244
- 3245 function disconnect()
- 3246 {
- 3247 $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 3248 if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
- 3249 fclose($this->realtime_log_file);
- 3250 }
- 3251 }
- 3252
- 3253
- 3254
- 3255
- 3256
- 3257
- 3258
- 3259
- 3260
- 3261 function __destruct()
- 3262 {
- 3263 $this->disconnect();
- 3264 }
- 3265
- 3266
- 3267
- 3268
- 3269
- 3270
- 3271
- 3272 function isConnected()
- 3273 {
- 3274 return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED);
- 3275 }
- 3276
- 3277
- 3278
- 3279
- 3280
- 3281
- 3282
- 3283 function isAuthenticated()
- 3284 {
- 3285 return (bool) ($this->bitmap & NET_SSH2_MASK_LOGIN);
- 3286 }
- 3287
- 3288
- 3289
- 3290
- 3291
- 3292
- 3293
- 3294 function _reset_connection($reason)
- 3295 {
- 3296 $this->_disconnect($reason);
- 3297 $this->decrypt = $this->encrypt = false;
- 3298 $this->decrypt_block_size = $this->encrypt_block_size = 8;
- 3299 $this->hmac_check = $this->hmac_create = false;
- 3300 $this->hmac_size = false;
- 3301 $this->session_id = false;
- 3302 $this->retry_connect = true;
- 3303 $this->get_seq_no = $this->send_seq_no = 0;
- 3304 }
- 3305
- 3306
- 3307
- 3308
- 3309
- 3310
- 3311
- 3312
- 3313
- 3314
- 3315 function _get_binary_packet($skip_channel_filter = false)
- 3316 {
- 3317 if (!is_resource($this->fsock) || feof($this->fsock)) {
- 3318 user_error('Connection closed prematurely');
- 3319 $this->bitmap = 0;
- 3320 return false;
- 3321 }
- 3322
- 3323 $start = strtok(microtime(), ' ') + strtok('');
- 3324 $raw = fread($this->fsock, $this->decrypt_block_size);
- 3325
- 3326 if (!strlen($raw)) {
- 3327 return '';
- 3328 }
- 3329
- 3330 if ($this->decrypt !== false) {
- 3331 $raw = $this->decrypt->decrypt($raw);
- 3332 }
- 3333 if ($raw === false) {
- 3334 user_error('Unable to decrypt content');
- 3335 return false;
- 3336 }
- 3337
- 3338 if (strlen($raw) < 5) {
- 3339 return false;
- 3340 }
- 3341 extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
- 3342
- 3343 $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
- 3344
- 3345
- 3346
- 3347
- 3348 if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
- 3349 if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt_algorithm) && !($this->bitmap & NET_SSH2_MASK_LOGIN)) {
- 3350 $this->bad_key_size_fix = true;
- 3351 $this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 3352 return false;
- 3353 }
- 3354 user_error('Invalid size');
- 3355 return false;
- 3356 }
- 3357
- 3358 $buffer = '';
- 3359 while ($remaining_length > 0) {
- 3360 $temp = fread($this->fsock, $remaining_length);
- 3361 if ($temp === false || feof($this->fsock)) {
- 3362 user_error('Error reading from socket');
- 3363 $this->bitmap = 0;
- 3364 return false;
- 3365 }
- 3366 $buffer.= $temp;
- 3367 $remaining_length-= strlen($temp);
- 3368 }
- 3369
- 3370 $stop = strtok(microtime(), ' ') + strtok('');
- 3371 if (strlen($buffer)) {
- 3372 $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
- 3373 }
- 3374
- 3375 $payload = $this->_string_shift($raw, $packet_length - $padding_length - 1);
- 3376 $padding = $this->_string_shift($raw, $padding_length);
- 3377
- 3378 if ($this->hmac_check !== false) {
- 3379 $hmac = fread($this->fsock, $this->hmac_size);
- 3380 if ($hmac === false || strlen($hmac) != $this->hmac_size) {
- 3381 user_error('Error reading socket');
- 3382 $this->bitmap = 0;
- 3383 return false;
- 3384 } elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
- 3385 user_error('Invalid HMAC');
- 3386 return false;
- 3387 }
- 3388 }
- 3389
- 3390
- 3391
- 3392
- 3393
- 3394 $this->get_seq_no++;
- 3395
- 3396 if (defined('NET_SSH2_LOGGING')) {
- 3397 $current = strtok(microtime(), ' ') + strtok('');
- 3398 $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
- 3399 $message_number = '<- ' . $message_number .
- 3400 ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
- 3401 $this->_append_log($message_number, $payload);
- 3402 $this->last_packet = $current;
- 3403 }
- 3404
- 3405 return $this->_filter($payload, $skip_channel_filter);
- 3406 }
- 3407
- 3408
- 3409
- 3410
- 3411
- 3412
- 3413
- 3414
- 3415
- 3416
- 3417 function _filter($payload, $skip_channel_filter)
- 3418 {
- 3419 switch (ord($payload[0])) {
- 3420 case NET_SSH2_MSG_DISCONNECT:
- 3421 $this->_string_shift($payload, 1);
- 3422 if (strlen($payload) < 8) {
- 3423 return false;
- 3424 }
- 3425 extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8)));
- 3426 $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $length));
- 3427 $this->bitmap = 0;
- 3428 return false;
- 3429 case NET_SSH2_MSG_IGNORE:
- 3430 $payload = $this->_get_binary_packet($skip_channel_filter);
- 3431 break;
- 3432 case NET_SSH2_MSG_DEBUG:
- 3433 $this->_string_shift($payload, 2);
- 3434 if (strlen($payload) < 4) {
- 3435 return false;
- 3436 }
- 3437 extract(unpack('Nlength', $this->_string_shift($payload, 4)));
- 3438 $this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode($this->_string_shift($payload, $length));
- 3439 $payload = $this->_get_binary_packet($skip_channel_filter);
- 3440 break;
- 3441 case NET_SSH2_MSG_UNIMPLEMENTED:
- 3442 return false;
- 3443 case NET_SSH2_MSG_KEXINIT:
- 3444 if ($this->session_id !== false) {
- 3445 $this->send_kex_first = false;
- 3446 if (!$this->_key_exchange($payload)) {
- 3447 $this->bitmap = 0;
- 3448 return false;
- 3449 }
- 3450 $payload = $this->_get_binary_packet($skip_channel_filter);
- 3451 }
- 3452 }
- 3453
- 3454
- 3455 if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
- 3456 $this->_string_shift($payload, 1);
- 3457 if (strlen($payload) < 4) {
- 3458 return false;
- 3459 }
- 3460 extract(unpack('Nlength', $this->_string_shift($payload, 4)));
- 3461 $this->banner_message = utf8_decode($this->_string_shift($payload, $length));
- 3462 $payload = $this->_get_binary_packet();
- 3463 }
- 3464
- 3465
- 3466 if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && $this->isAuthenticated()) {
- 3467 switch (ord($payload[0])) {
- 3468 case NET_SSH2_MSG_CHANNEL_DATA:
- 3469 case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
- 3470 case NET_SSH2_MSG_CHANNEL_REQUEST:
- 3471 case NET_SSH2_MSG_CHANNEL_CLOSE:
- 3472 case NET_SSH2_MSG_CHANNEL_EOF:
- 3473 if (!$skip_channel_filter && !empty($this->server_channels)) {
- 3474 $this->binary_packet_buffer = $payload;
- 3475 $this->_get_channel_packet(true);
- 3476 $payload = $this->_get_binary_packet();
- 3477 }
- 3478 break;
- 3479 case NET_SSH2_MSG_GLOBAL_REQUEST:
- 3480 if (strlen($payload) < 4) {
- 3481 return false;
- 3482 }
- 3483 extract(unpack('Nlength', $this->_string_shift($payload, 4)));
- 3484 $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
- 3485
- 3486 if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) {
- 3487 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 3488 }
- 3489
- 3490 $payload = $this->_get_binary_packet($skip_channel_filter);
- 3491 break;
- 3492 case NET_SSH2_MSG_CHANNEL_OPEN:
- 3493 $this->_string_shift($payload, 1);
- 3494 if (strlen($payload) < 4) {
- 3495 return false;
- 3496 }
- 3497 extract(unpack('Nlength', $this->_string_shift($payload, 4)));
- 3498 $data = $this->_string_shift($payload, $length);
- 3499 if (strlen($payload) < 4) {
- 3500 return false;
- 3501 }
- 3502 extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
- 3503 switch ($data) {
- 3504 case 'auth-agent':
- 3505 case 'auth-agent@openssh.com':
- 3506 if (isset($this->agent)) {
- 3507 $new_channel = NET_SSH2_CHANNEL_AGENT_FORWARD;
- 3508
- 3509 if (strlen($payload) < 8) {
- 3510 return false;
- 3511 }
- 3512 extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
- 3513 extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
- 3514
- 3515 $this->packet_size_client_to_server[$new_channel] = $remote_window_size;
- 3516 $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
- 3517 $this->window_size_client_to_server[$new_channel] = $this->window_size;
- 3518
- 3519 $packet_size = 0x4000;
- 3520
- 3521 $packet = pack(
- 3522 'CN4',
- 3523 NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
- 3524 $server_channel,
- 3525 $new_channel,
- 3526 $packet_size,
- 3527 $packet_size
- 3528 );
- 3529
- 3530 $this->server_channels[$new_channel] = $server_channel;
- 3531 $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
- 3532 if (!$this->_send_binary_packet($packet)) {
- 3533 return false;
- 3534 }
- 3535 }
- 3536 break;
- 3537 default:
- 3538 $packet = pack(
- 3539 'CN3a*Na*',
- 3540 NET_SSH2_MSG_REQUEST_FAILURE,
- 3541 $server_channel,
- 3542 NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
- 3543 0,
- 3544 '',
- 3545 0,
- 3546 ''
- 3547 );
- 3548
- 3549 if (!$this->_send_binary_packet($packet)) {
- 3550 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 3551 }
- 3552 }
- 3553 $payload = $this->_get_binary_packet($skip_channel_filter);
- 3554 break;
- 3555 case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
- 3556 $this->_string_shift($payload, 1);
- 3557 if (strlen($payload) < 8) {
- 3558 return false;
- 3559 }
- 3560 extract(unpack('Nchannel', $this->_string_shift($payload, 4)));
- 3561 extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
- 3562 $this->window_size_client_to_server[$channel]+= $window_size;
- 3563
- 3564 $payload = ($this->bitmap & NET_SSH2_MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet($skip_channel_filter);
- 3565 }
- 3566 }
- 3567
- 3568 return $payload;
- 3569 }
- 3570
- 3571
- 3572
- 3573
- 3574
- 3575
- 3576
- 3577
- 3578 function enableQuietMode()
- 3579 {
- 3580 $this->quiet_mode = true;
- 3581 }
- 3582
- 3583
- 3584
- 3585
- 3586
- 3587
- 3588
- 3589
- 3590 function disableQuietMode()
- 3591 {
- 3592 $this->quiet_mode = false;
- 3593 }
- 3594
- 3595
- 3596
- 3597
- 3598
- 3599
- 3600
- 3601
- 3602
- 3603
- 3604 function isQuietModeEnabled()
- 3605 {
- 3606 return $this->quiet_mode;
- 3607 }
- 3608
- 3609
- 3610
- 3611
- 3612
- 3613
- 3614 function enablePTY()
- 3615 {
- 3616 $this->request_pty = true;
- 3617 }
- 3618
- 3619
- 3620
- 3621
- 3622
- 3623
- 3624 function disablePTY()
- 3625 {
- 3626 if ($this->in_request_pty_exec) {
- 3627 $this->_close_channel(NET_SSH2_CHANNEL_EXEC);
- 3628 $this->in_request_pty_exec = false;
- 3629 }
- 3630 $this->request_pty = false;
- 3631 }
- 3632
- 3633
- 3634
- 3635
- 3636
- 3637
- 3638
- 3639
- 3640
- 3641
- 3642 function isPTYEnabled()
- 3643 {
- 3644 return $this->request_pty;
- 3645 }
- 3646
- 3647
- 3648
- 3649
- 3650
- 3651
- 3652
- 3653
- 3654
- 3655
- 3656 function _get_channel_packet($client_channel, $skip_extended = false)
- 3657 {
- 3658 if (!empty($this->channel_buffers[$client_channel])) {
- 3659 return array_shift($this->channel_buffers[$client_channel]);
- 3660 }
- 3661
- 3662 while (true) {
- 3663 if ($this->binary_packet_buffer !== false) {
- 3664 $response = $this->binary_packet_buffer;
- 3665 $this->binary_packet_buffer = false;
- 3666 } else {
- 3667 if ($this->curTimeout) {
- 3668 if ($this->curTimeout < 0) {
- 3669 $this->is_timeout = true;
- 3670 return true;
- 3671 }
- 3672
- 3673 $read = array($this->fsock);
- 3674 $write = $except = null;
- 3675
- 3676 $start = strtok(microtime(), ' ') + strtok('');
- 3677 $sec = floor($this->curTimeout);
- 3678 $usec = 1000000 * ($this->curTimeout - $sec);
- 3679
- 3680 if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
- 3681 $this->is_timeout = true;
- 3682 return true;
- 3683 }
- 3684 $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
- 3685 $this->curTimeout-= $elapsed;
- 3686 }
- 3687
- 3688 $response = $this->_get_binary_packet(true);
- 3689 if ($response === false) {
- 3690 user_error('Connection closed by server');
- 3691 return false;
- 3692 }
- 3693 }
- 3694
- 3695 if ($client_channel == -1 && $response === true) {
- 3696 return true;
- 3697 }
- 3698 if (!strlen($response)) {
- 3699 return '';
- 3700 }
- 3701
- 3702 if (!strlen($response)) {
- 3703 return false;
- 3704 }
- 3705 extract(unpack('Ctype', $this->_string_shift($response, 1)));
- 3706
- 3707 if (strlen($response) < 4) {
- 3708 return false;
- 3709 }
- 3710 if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
- 3711 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 3712 } else {
- 3713 extract(unpack('Nchannel', $this->_string_shift($response, 4)));
- 3714 }
- 3715
- 3716
- 3717 if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
- 3718 $this->window_size_server_to_client[$channel]-= strlen($response);
- 3719
- 3720
- 3721 if ($this->window_size_server_to_client[$channel] < 0) {
- 3722 $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size);
- 3723 if (!$this->_send_binary_packet($packet)) {
- 3724 return false;
- 3725 }
- 3726 $this->window_size_server_to_client[$channel]+= $this->window_size;
- 3727 }
- 3728
- 3729 switch ($type) {
- 3730 case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
- 3731
- 3732
- 3733
- 3734
- 3735
- 3736
- 3737 if (strlen($response) < 8) {
- 3738 return false;
- 3739 }
- 3740 extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
- 3741 $data = $this->_string_shift($response, $length);
- 3742 $this->stdErrorLog.= $data;
- 3743 if ($skip_extended || $this->quiet_mode) {
- 3744 continue 2;
- 3745 }
- 3746 if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
- 3747 return $data;
- 3748 }
- 3749 if (!isset($this->channel_buffers[$channel])) {
- 3750 $this->channel_buffers[$channel] = array();
- 3751 }
- 3752 $this->channel_buffers[$channel][] = $data;
- 3753
- 3754 continue 2;
- 3755 case NET_SSH2_MSG_CHANNEL_REQUEST:
- 3756 if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) {
- 3757 continue 2;
- 3758 }
- 3759 if (strlen($response) < 4) {
- 3760 return false;
- 3761 }
- 3762 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 3763 $value = $this->_string_shift($response, $length);
- 3764 switch ($value) {
- 3765 case 'exit-signal':
- 3766 $this->_string_shift($response, 1);
- 3767 if (strlen($response) < 4) {
- 3768 return false;
- 3769 }
- 3770 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 3771 $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
- 3772 $this->_string_shift($response, 1);
- 3773 if (strlen($response) < 4) {
- 3774 return false;
- 3775 }
- 3776 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 3777 if ($length) {
- 3778 $this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
- 3779 }
- 3780
- 3781 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
- 3782 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
- 3783
- 3784 $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
- 3785
- 3786 continue 3;
- 3787 case 'exit-status':
- 3788 if (strlen($response) < 5) {
- 3789 return false;
- 3790 }
- 3791 extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
- 3792 $this->exit_status = $exit_status;
- 3793
- 3794
- 3795
- 3796
- 3797 continue 3;
- 3798 default:
- 3799
- 3800
- 3801 continue 3;
- 3802 }
- 3803 }
- 3804
- 3805 switch ($this->channel_status[$channel]) {
- 3806 case NET_SSH2_MSG_CHANNEL_OPEN:
- 3807 switch ($type) {
- 3808 case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
- 3809 if (strlen($response) < 4) {
- 3810 return false;
- 3811 }
- 3812 extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
- 3813 $this->server_channels[$channel] = $server_channel;
- 3814 if (strlen($response) < 4) {
- 3815 return false;
- 3816 }
- 3817 extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
- 3818 if ($window_size < 0) {
- 3819 $window_size&= 0x7FFFFFFF;
- 3820 $window_size+= 0x80000000;
- 3821 }
- 3822 $this->window_size_client_to_server[$channel] = $window_size;
- 3823 if (strlen($response) < 4) {
- 3824 return false;
- 3825 }
- 3826 $temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
- 3827 $this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
- 3828 $result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
- 3829 $this->_on_channel_open();
- 3830 return $result;
- 3831
- 3832 default:
- 3833 user_error('Unable to open channel');
- 3834 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 3835 }
- 3836 break;
- 3837 case NET_SSH2_MSG_CHANNEL_REQUEST:
- 3838 switch ($type) {
- 3839 case NET_SSH2_MSG_CHANNEL_SUCCESS:
- 3840 return true;
- 3841 case NET_SSH2_MSG_CHANNEL_FAILURE:
- 3842 return false;
- 3843 default:
- 3844 user_error('Unable to fulfill channel request');
- 3845 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 3846 }
- 3847 case NET_SSH2_MSG_CHANNEL_CLOSE:
- 3848 return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
- 3849 }
- 3850 }
- 3851
- 3852
- 3853
- 3854 switch ($type) {
- 3855 case NET_SSH2_MSG_CHANNEL_DATA:
- 3856
- 3857
- 3858
- 3859
- 3860
- 3861
- 3862
- 3863
- 3864
- 3865 if (strlen($response) < 4) {
- 3866 return false;
- 3867 }
- 3868 extract(unpack('Nlength', $this->_string_shift($response, 4)));
- 3869 $data = $this->_string_shift($response, $length);
- 3870
- 3871 if ($channel == NET_SSH2_CHANNEL_AGENT_FORWARD) {
- 3872 $agent_response = $this->agent->_forward_data($data);
- 3873 if (!is_bool($agent_response)) {
- 3874 $this->_send_channel_packet($channel, $agent_response);
- 3875 }
- 3876 break;
- 3877 }
- 3878
- 3879 if ($client_channel == $channel) {
- 3880 return $data;
- 3881 }
- 3882 if (!isset($this->channel_buffers[$channel])) {
- 3883 $this->channel_buffers[$channel] = array();
- 3884 }
- 3885 $this->channel_buffers[$channel][] = $data;
- 3886 break;
- 3887 case NET_SSH2_MSG_CHANNEL_CLOSE:
- 3888 $this->curTimeout = 0;
- 3889
- 3890 if ($this->bitmap & NET_SSH2_MASK_SHELL) {
- 3891 $this->bitmap&= ~NET_SSH2_MASK_SHELL;
- 3892 }
- 3893 if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) {
- 3894 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
- 3895 }
- 3896
- 3897 $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
- 3898 if ($client_channel == $channel) {
- 3899 return true;
- 3900 }
- 3901 case NET_SSH2_MSG_CHANNEL_EOF:
- 3902 break;
- 3903 default:
- 3904 user_error('Error reading channel data');
- 3905 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- 3906 }
- 3907 }
- 3908 }
- 3909
- 3910
- 3911
- 3912
- 3913
- 3914
- 3915
- 3916
- 3917
- 3918
- 3919
- 3920
- 3921 function _send_binary_packet($data, $logged = null)
- 3922 {
- 3923 if (!is_resource($this->fsock) || feof($this->fsock)) {
- 3924 user_error('Connection closed prematurely');
- 3925 $this->bitmap = 0;
- 3926 return false;
- 3927 }
- 3928
- 3929
- 3930
- 3931
- 3932
- 3933
- 3934
- 3935
- 3936 $packet_length = strlen($data) + 9;
- 3937
- 3938 $packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size;
- 3939
- 3940 $padding_length = $packet_length - strlen($data) - 5;
- 3941 $padding = crypt_random_string($padding_length);
- 3942
- 3943
- 3944 $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
- 3945
- 3946 $hmac = $this->hmac_create !== false ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : '';
- 3947 $this->send_seq_no++;
- 3948
- 3949 if ($this->encrypt !== false) {
- 3950 $packet = $this->encrypt->encrypt($packet);
- 3951 }
- 3952
- 3953 $packet.= $hmac;
- 3954
- 3955 $start = strtok(microtime(), ' ') + strtok('');
- 3956 $result = strlen($packet) == fputs($this->fsock, $packet);
- 3957 $stop = strtok(microtime(), ' ') + strtok('');
- 3958
- 3959 if (defined('NET_SSH2_LOGGING')) {
- 3960 $current = strtok(microtime(), ' ') + strtok('');
- 3961 $message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')';
- 3962 $message_number = '-> ' . $message_number .
- 3963 ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
- 3964 $this->_append_log($message_number, isset($logged) ? $logged : $data);
- 3965 $this->last_packet = $current;
- 3966 }
- 3967
- 3968 return $result;
- 3969 }
- 3970
- 3971
- 3972
- 3973
- 3974
- 3975
- 3976
- 3977
- 3978
- 3979 function _append_log($message_number, $message)
- 3980 {
- 3981
- 3982 if (strlen($message_number) > 2) {
- 3983 $this->_string_shift($message);
- 3984 }
- 3985
- 3986 switch (NET_SSH2_LOGGING) {
- 3987
- 3988 case NET_SSH2_LOG_SIMPLE:
- 3989 $this->message_number_log[] = $message_number;
- 3990 break;
- 3991
- 3992 case NET_SSH2_LOG_COMPLEX:
- 3993 $this->message_number_log[] = $message_number;
- 3994 $this->log_size+= strlen($message);
- 3995 $this->message_log[] = $message;
- 3996 while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) {
- 3997 $this->log_size-= strlen(array_shift($this->message_log));
- 3998 array_shift($this->message_number_log);
- 3999 }
- 4000 break;
- 4001
- 4002
- 4003
- 4004 case NET_SSH2_LOG_REALTIME:
- 4005 switch (PHP_SAPI) {
- 4006 case 'cli':
- 4007 $start = $stop = "\r\n";
- 4008 break;
- 4009 default:
- 4010 $start = '<pre>';
- 4011 $stop = '</pre>';
- 4012 }
- 4013 echo $start . $this->_format_log(array($message), array($message_number)) . $stop;
- 4014 @flush();
- 4015 @ob_flush();
- 4016 break;
- 4017
- 4018
- 4019
- 4020
- 4021 case NET_SSH2_LOG_REALTIME_FILE:
- 4022 if (!isset($this->realtime_log_file)) {
- 4023
- 4024 $filename = NET_SSH2_LOG_REALTIME_FILENAME;
- 4025 $fp = fopen($filename, 'w');
- 4026 $this->realtime_log_file = $fp;
- 4027 }
- 4028 if (!is_resource($this->realtime_log_file)) {
- 4029 break;
- 4030 }
- 4031 $entry = $this->_format_log(array($message), array($message_number));
- 4032 if ($this->realtime_log_wrap) {
- 4033 $temp = "<<< START >>>\r\n";
- 4034 $entry.= $temp;
- 4035 fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
- 4036 }
- 4037 $this->realtime_log_size+= strlen($entry);
- 4038 if ($this->realtime_log_size > NET_SSH2_LOG_MAX_SIZE) {
- 4039 fseek($this->realtime_log_file, 0);
- 4040 $this->realtime_log_size = strlen($entry);
- 4041 $this->realtime_log_wrap = true;
- 4042 }
- 4043 fputs($this->realtime_log_file, $entry);
- 4044 }
- 4045 }
- 4046
- 4047
- 4048
- 4049
- 4050
- 4051
- 4052
- 4053
- 4054
- 4055
- 4056
- 4057 function _send_channel_packet($client_channel, $data)
- 4058 {
- 4059 while (strlen($data)) {
- 4060 if (!$this->window_size_client_to_server[$client_channel]) {
- 4061 $this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
- 4062
- 4063 $this->_get_channel_packet(-1);
- 4064 $this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
- 4065 }
- 4066
- 4067
- 4068
- 4069
- 4070
- 4071 $max_size = min(
- 4072 $this->packet_size_client_to_server[$client_channel],
- 4073 $this->window_size_client_to_server[$client_channel]
- 4074 );
- 4075
- 4076 $temp = $this->_string_shift($data, $max_size);
- 4077 $packet = pack(
- 4078 'CN2a*',
- 4079 NET_SSH2_MSG_CHANNEL_DATA,
- 4080 $this->server_channels[$client_channel],
- 4081 strlen($temp),
- 4082 $temp
- 4083 );
- 4084 $this->window_size_client_to_server[$client_channel]-= strlen($temp);
- 4085 if (!$this->_send_binary_packet($packet)) {
- 4086 return false;
- 4087 }
- 4088 }
- 4089
- 4090 return true;
- 4091 }
- 4092
- 4093
- 4094
- 4095
- 4096
- 4097
- 4098
- 4099
- 4100
- 4101
- 4102
- 4103
- 4104
- 4105 function _close_channel($client_channel, $want_reply = false)
- 4106 {
- 4107
- 4108
- 4109 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
- 4110
- 4111 if (!$want_reply) {
- 4112 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
- 4113 }
- 4114
- 4115 $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
- 4116
- 4117 $this->curTimeout = 0;
- 4118
- 4119 while (!is_bool($this->_get_channel_packet($client_channel))) {
- 4120 }
- 4121
- 4122 if ($want_reply) {
- 4123 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
- 4124 }
- 4125
- 4126 if ($this->bitmap & NET_SSH2_MASK_SHELL) {
- 4127 $this->bitmap&= ~NET_SSH2_MASK_SHELL;
- 4128 }
- 4129 }
- 4130
- 4131
- 4132
- 4133
- 4134
- 4135
- 4136
- 4137
- 4138 function _disconnect($reason)
- 4139 {
- 4140 if ($this->bitmap & NET_SSH2_MASK_CONNECTED) {
- 4141 $data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
- 4142 $this->_send_binary_packet($data);
- 4143 $this->bitmap = 0;
- 4144 fclose($this->fsock);
- 4145 return false;
- 4146 }
- 4147 }
- 4148
- 4149
- 4150
- 4151
- 4152
- 4153
- 4154
- 4155
- 4156
- 4157
- 4158
- 4159 function _string_shift(&$string, $index = 1)
- 4160 {
- 4161 $substr = substr($string, 0, $index);
- 4162 $string = substr($string, $index);
- 4163 return $substr;
- 4164 }
- 4165
- 4166
- 4167
- 4168
- 4169
- 4170
- 4171
- 4172
- 4173
- 4174
- 4175
- 4176 function _define_array()
- 4177 {
- 4178 $args = func_get_args();
- 4179 foreach ($args as $arg) {
- 4180 foreach ($arg as $key => $value) {
- 4181 if (!defined($value)) {
- 4182 define($value, $key);
- 4183 } else {
- 4184 break 2;
- 4185 }
- 4186 }
- 4187 }
- 4188 }
- 4189
- 4190
- 4191
- 4192
- 4193
- 4194
- 4195
- 4196
- 4197
- 4198 function getLog()
- 4199 {
- 4200 if (!defined('NET_SSH2_LOGGING')) {
- 4201 return false;
- 4202 }
- 4203
- 4204 switch (NET_SSH2_LOGGING) {
- 4205 case NET_SSH2_LOG_SIMPLE:
- 4206 return $this->message_number_log;
- 4207 case NET_SSH2_LOG_COMPLEX:
- 4208 $log = $this->_format_log($this->message_log, $this->message_number_log);
- 4209 return PHP_SAPI == 'cli' ? $log : '<pre>' . $log . '</pre>';
- 4210 default:
- 4211 return false;
- 4212 }
- 4213 }
- 4214
- 4215
- 4216
- 4217
- 4218
- 4219
- 4220
- 4221
- 4222
- 4223 function _format_log($message_log, $message_number_log)
- 4224 {
- 4225 $output = '';
- 4226 for ($i = 0; $i < count($message_log); $i++) {
- 4227 $output.= $message_number_log[$i] . "\r\n";
- 4228 $current_log = $message_log[$i];
- 4229 $j = 0;
- 4230 do {
- 4231 if (strlen($current_log)) {
- 4232 $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
- 4233 }
- 4234 $fragment = $this->_string_shift($current_log, $this->log_short_width);
- 4235 $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary));
- 4236
- 4237
- 4238
- 4239 $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
- 4240 $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n";
- 4241 $j++;
- 4242 } while (strlen($current_log));
- 4243 $output.= "\r\n";
- 4244 }
- 4245
- 4246 return $output;
- 4247 }
- 4248
- 4249
- 4250
- 4251
- 4252
- 4253
- 4254
- 4255
- 4256
- 4257
- 4258 function _format_log_helper($matches)
- 4259 {
- 4260 return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
- 4261 }
- 4262
- 4263
- 4264
- 4265
- 4266
- 4267
- 4268
- 4269
- 4270
- 4271
- 4272 function _on_channel_open()
- 4273 {
- 4274 if (isset($this->agent)) {
- 4275 $this->agent->_on_channel_open($this);
- 4276 }
- 4277 }
- 4278
- 4279
- 4280
- 4281
- 4282
- 4283
- 4284
- 4285
- 4286
- 4287
- 4288 function _array_intersect_first($array1, $array2)
- 4289 {
- 4290 foreach ($array1 as $value) {
- 4291 if (in_array($value, $array2)) {
- 4292 return $value;
- 4293 }
- 4294 }
- 4295 return false;
- 4296 }
- 4297
- 4298
- 4299
- 4300
- 4301
- 4302
- 4303
- 4304 function getErrors()
- 4305 {
- 4306 return $this->errors;
- 4307 }
- 4308
- 4309
- 4310
- 4311
- 4312
- 4313
- 4314
- 4315 function getLastError()
- 4316 {
- 4317 $count = count($this->errors);
- 4318
- 4319 if ($count > 0) {
- 4320 return $this->errors[$count - 1];
- 4321 }
- 4322 }
- 4323
- 4324
- 4325
- 4326
- 4327
- 4328
- 4329
- 4330 function getServerIdentification()
- 4331 {
- 4332 $this->_connect();
- 4333
- 4334 return $this->server_identifier;
- 4335 }
- 4336
- 4337
- 4338
- 4339
- 4340
- 4341
- 4342
- 4343 function getKexAlgorithms()
- 4344 {
- 4345 $this->_connect();
- 4346
- 4347 return $this->kex_algorithms;
- 4348 }
- 4349
- 4350
- 4351
- 4352
- 4353
- 4354
- 4355
- 4356 function getServerHostKeyAlgorithms()
- 4357 {
- 4358 $this->_connect();
- 4359
- 4360 return $this->server_host_key_algorithms;
- 4361 }
- 4362
- 4363
- 4364
- 4365
- 4366
- 4367
- 4368
- 4369 function getEncryptionAlgorithmsClient2Server()
- 4370 {
- 4371 $this->_connect();
- 4372
- 4373 return $this->encryption_algorithms_client_to_server;
- 4374 }
- 4375
- 4376
- 4377
- 4378
- 4379
- 4380
- 4381
- 4382 function getEncryptionAlgorithmsServer2Client()
- 4383 {
- 4384 $this->_connect();
- 4385
- 4386 return $this->encryption_algorithms_server_to_client;
- 4387 }
- 4388
- 4389
- 4390
- 4391
- 4392
- 4393
- 4394
- 4395 function getMACAlgorithmsClient2Server()
- 4396 {
- 4397 $this->_connect();
- 4398
- 4399 return $this->mac_algorithms_client_to_server;
- 4400 }
- 4401
- 4402
- 4403
- 4404
- 4405
- 4406
- 4407
- 4408 function getMACAlgorithmsServer2Client()
- 4409 {
- 4410 $this->_connect();
- 4411
- 4412 return $this->mac_algorithms_server_to_client;
- 4413 }
- 4414
- 4415
- 4416
- 4417
- 4418
- 4419
- 4420
- 4421 function getCompressionAlgorithmsClient2Server()
- 4422 {
- 4423 $this->_connect();
- 4424
- 4425 return $this->compression_algorithms_client_to_server;
- 4426 }
- 4427
- 4428
- 4429
- 4430
- 4431
- 4432
- 4433
- 4434 function getCompressionAlgorithmsServer2Client()
- 4435 {
- 4436 $this->_connect();
- 4437
- 4438 return $this->compression_algorithms_server_to_client;
- 4439 }
- 4440
- 4441
- 4442
- 4443
- 4444
- 4445
- 4446
- 4447 function getLanguagesServer2Client()
- 4448 {
- 4449 $this->_connect();
- 4450
- 4451 return $this->languages_server_to_client;
- 4452 }
- 4453
- 4454
- 4455
- 4456
- 4457
- 4458
- 4459
- 4460 function getLanguagesClient2Server()
- 4461 {
- 4462 $this->_connect();
- 4463
- 4464 return $this->languages_client_to_server;
- 4465 }
- 4466
- 4467
- 4468
- 4469
- 4470
- 4471
- 4472
- 4473
- 4474
- 4475
- 4476 function getBannerMessage()
- 4477 {
- 4478 return $this->banner_message;
- 4479 }
- 4480
- 4481
- 4482
- 4483
- 4484
- 4485
- 4486
- 4487
- 4488
- 4489
- 4490 function getServerPublicHostKey()
- 4491 {
- 4492 if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
- 4493 if (!$this->_connect()) {
- 4494 return false;
- 4495 }
- 4496 }
- 4497
- 4498 $signature = $this->signature;
- 4499 $server_public_host_key = $this->server_public_host_key;
- 4500
- 4501 if (strlen($server_public_host_key) < 4) {
- 4502 return false;
- 4503 }
- 4504 extract(unpack('Nlength', $this->_string_shift($server_public_host_key, 4)));
- 4505 $this->_string_shift($server_public_host_key, $length);
- 4506
- 4507 if ($this->signature_validated) {
- 4508 return $this->bitmap ?
- 4509 $this->signature_format . ' ' . base64_encode($this->server_public_host_key) :
- 4510 false;
- 4511 }
- 4512
- 4513 $this->signature_validated = true;
- 4514
- 4515 switch ($this->signature_format) {
- 4516 case 'ssh-dss':
- 4517 $zero = new Math_BigInteger();
- 4518
- 4519 if (strlen($server_public_host_key) < 4) {
- 4520 return false;
- 4521 }
- 4522 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 4523 $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- 4524
- 4525 if (strlen($server_public_host_key) < 4) {
- 4526 return false;
- 4527 }
- 4528 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 4529 $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- 4530
- 4531 if (strlen($server_public_host_key) < 4) {
- 4532 return false;
- 4533 }
- 4534 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 4535 $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- 4536
- 4537 if (strlen($server_public_host_key) < 4) {
- 4538 return false;
- 4539 }
- 4540 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 4541 $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- 4542
- 4543
- 4544
- 4545
- 4546 $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- 4547 if ($temp['length'] != 40) {
- 4548 user_error('Invalid signature');
- 4549 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 4550 }
- 4551
- 4552 $r = new Math_BigInteger($this->_string_shift($signature, 20), 256);
- 4553 $s = new Math_BigInteger($this->_string_shift($signature, 20), 256);
- 4554
- 4555 switch (true) {
- 4556 case $r->equals($zero):
- 4557 case $r->compare($q) >= 0:
- 4558 case $s->equals($zero):
- 4559 case $s->compare($q) >= 0:
- 4560 user_error('Invalid signature');
- 4561 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 4562 }
- 4563
- 4564 $w = $s->modInverse($q);
- 4565
- 4566 $u1 = $w->multiply(new Math_BigInteger(sha1($this->exchange_hash), 16));
- 4567 list(, $u1) = $u1->divide($q);
- 4568
- 4569 $u2 = $w->multiply($r);
- 4570 list(, $u2) = $u2->divide($q);
- 4571
- 4572 $g = $g->modPow($u1, $p);
- 4573 $y = $y->modPow($u2, $p);
- 4574
- 4575 $v = $g->multiply($y);
- 4576 list(, $v) = $v->divide($p);
- 4577 list(, $v) = $v->divide($q);
- 4578
- 4579 if (!$v->equals($r)) {
- 4580 user_error('Bad server signature');
- 4581 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- 4582 }
- 4583
- 4584 break;
- 4585 case 'ssh-rsa':
- 4586 if (strlen($server_public_host_key) < 4) {
- 4587 return false;
- 4588 }
- 4589 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 4590 $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- 4591
- 4592 if (strlen($server_public_host_key) < 4) {
- 4593 return false;
- 4594 }
- 4595 $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- 4596 $rawN = $this->_string_shift($server_public_host_key, $temp['length']);
- 4597 $n = new Math_BigInteger($rawN, -256);
- 4598 $nLength = strlen(ltrim($rawN, "\0"));
- 4599
- 4600
- 4601
- 4602
- 4603
- 4604
- 4605
- 4606
- 4607
- 4608
- 4609
- 4610
- 4611
- 4612
- 4613
- 4614
- 4615
- 4616
- 4617
- 4618
- 4619
- 4620 if (strlen($signature) < 4) {
- 4621 return false;
- 4622 }
- 4623 $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- 4624 $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
- 4625
- 4626
- 4627
- 4628
- 4629
- 4630
- 4631
- 4632 if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) {
- 4633 user_error('Invalid signature');
- 4634 return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- 4635 }
- 4636
- 4637 $s = $s->modPow($e, $n);
- 4638 $s = $s->toBytes();
- 4639
- 4640 $h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($this->exchange_hash));
- 4641 $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
- 4642
- 4643 if ($s != $h) {
- 4644 user_error('Bad server signature');
- 4645 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- 4646 }
- 4647 break;
- 4648 default:
- 4649 user_error('Unsupported signature format');
- 4650 return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- 4651 }
- 4652
- 4653 return $this->signature_format . ' ' . base64_encode($this->server_public_host_key);
- 4654 }
- 4655
- 4656
- 4657
- 4658
- 4659
- 4660
- 4661
- 4662 function getExitStatus()
- 4663 {
- 4664 if (is_null($this->exit_status)) {
- 4665 return false;
- 4666 }
- 4667 return $this->exit_status;
- 4668 }
- 4669
- 4670
- 4671
- 4672
- 4673
- 4674
- 4675
- 4676 function getWindowColumns()
- 4677 {
- 4678 return $this->windowColumns;
- 4679 }
- 4680
- 4681
- 4682
- 4683
- 4684
- 4685
- 4686
- 4687 function getWindowRows()
- 4688 {
- 4689 return $this->windowRows;
- 4690 }
- 4691
- 4692
- 4693
- 4694
- 4695
- 4696
- 4697
- 4698 function setWindowColumns($value)
- 4699 {
- 4700 $this->windowColumns = $value;
- 4701 }
- 4702
- 4703
- 4704
- 4705
- 4706
- 4707
- 4708
- 4709 function setWindowRows($value)
- 4710 {
- 4711 $this->windowRows = $value;
- 4712 }
- 4713
- 4714
- 4715
- 4716
- 4717
- 4718
- 4719
- 4720
- 4721 function setWindowSize($columns = 80, $rows = 24)
- 4722 {
- 4723 $this->windowColumns = $columns;
- 4724 $this->windowRows = $rows;
- 4725 }
- 4726 }